ReactOS  r76032
datetime.c
Go to the documentation of this file.
1 /*
2  * Date and time picker control
3  *
4  * Copyright 1998, 1999 Eric Kohl
5  * Copyright 1999, 2000 Alex Priem <alexp@sci.kun.nl>
6  * Copyright 2000 Chris Morgan <cmorgan@wpi.edu>
7  * Copyright 2012 Owen Rudge for CodeWeavers
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  *
23  * NOTE
24  *
25  * This code was audited for completeness against the documented features
26  * of Comctl32.dll version 6.0 on Oct. 20, 2004, by Dimitrie O. Paun.
27  *
28  * Unless otherwise noted, we believe this code to be complete, as per
29  * the specification mentioned above.
30  * If you discover missing features, or bugs, please note them below.
31  *
32  * TODO:
33  * -- DTS_APPCANPARSE
34  * -- DTS_SHORTDATECENTURYFORMAT
35  * -- DTN_FORMAT
36  * -- DTN_FORMATQUERY
37  * -- DTN_USERSTRING
38  * -- DTN_WMKEYDOWN
39  * -- FORMATCALLBACK
40  */
41 
42 #include "comctl32.h"
43 
44 #include <math.h>
45 
47 
48 typedef struct
49 {
58  RECT rcClient; /* rect around the edge of the window */
59  RECT rcDraw; /* rect inside of the border */
60  RECT checkbox; /* checkbox allowing the control to be enabled/disabled */
61  RECT calbutton; /* button that toggles the dropdown of the monthcal control */
62  BOOL bCalDepressed; /* TRUE = cal button is depressed */
64  int select;
65  WCHAR charsEntered[4];
69  int nrFields;
70  int haveFocus;
71  int *fieldspec;
73  int *buflen;
74  WCHAR textbuf[256];
78 
79 /* in monthcal.c */
80 extern int MONTHCAL_MonthLength(int month, int year);
81 extern int MONTHCAL_CalculateDayOfWeek(SYSTEMTIME *date, BOOL inplace);
82 
83 /* this list of defines is closely related to `allowedformatchars' defined
84  * in datetime.c; the high nibble indicates the `base type' of the format
85  * specifier.
86  * Do not change without first reading DATETIME_UseFormat.
87  *
88  */
89 
90 #define DT_END_FORMAT 0
91 #define ONEDIGITDAY 0x01
92 #define TWODIGITDAY 0x02
93 #define THREECHARDAY 0x03
94 #define FULLDAY 0x04
95 #define ONEDIGIT12HOUR 0x11
96 #define TWODIGIT12HOUR 0x12
97 #define ONEDIGIT24HOUR 0x21
98 #define TWODIGIT24HOUR 0x22
99 #define ONEDIGITMINUTE 0x31
100 #define TWODIGITMINUTE 0x32
101 #define ONEDIGITMONTH 0x41
102 #define TWODIGITMONTH 0x42
103 #define THREECHARMONTH 0x43
104 #define FULLMONTH 0x44
105 #define ONEDIGITSECOND 0x51
106 #define TWODIGITSECOND 0x52
107 #define ONELETTERAMPM 0x61
108 #define TWOLETTERAMPM 0x62
109 #define ONEDIGITYEAR 0x71
110 #define TWODIGITYEAR 0x72
111 #define INVALIDFULLYEAR 0x73 /* FIXME - yyy is not valid - we'll treat it as yyyy */
112 #define FULLYEAR 0x74
113 #define FORMATCALLBACK 0x81 /* -> maximum of 0x80 callbacks possible */
114 #define FORMATCALLMASK 0x80
115 #define DT_STRING 0x0100
116 
117 #define DTHT_DATEFIELD 0xff /* for hit-testing */
118 
119 #define DTHT_NONE 0x1000
120 #define DTHT_CHECKBOX 0x2000 /* these should end at '00' , to make */
121 #define DTHT_MCPOPUP 0x3000 /* & DTHT_DATEFIELD 0 when DATETIME_KeyDown */
122 #define DTHT_GOTFOCUS 0x4000 /* tests for date-fields */
123 #define DTHT_NODATEMASK 0xf000 /* to mask check and drop down from others */
124 
125 static BOOL DATETIME_SendSimpleNotify (const DATETIME_INFO *infoPtr, UINT code);
127 static const WCHAR allowedformatchars[] = {'d', 'h', 'H', 'm', 'M', 's', 't', 'y', 'X', 0};
128 static const int maxrepetition [] = {4,2,2,2,4,2,2,4,-1};
129 
130 /* valid date limits */
131 static const SYSTEMTIME max_allowed_date = { /* wYear */ 9999, /* wMonth */ 12, /* wDayOfWeek */ 0, /* wDay */ 31 };
132 static const SYSTEMTIME min_allowed_date = { /* wYear */ 1752, /* wMonth */ 9, /* wDayOfWeek */ 0, /* wDay */ 14 };
133 
134 static DWORD
136 {
137  if (!systime) return GDT_NONE;
138 
139  if ((infoPtr->dwStyle & DTS_SHOWNONE) &&
140  (SendMessageW (infoPtr->hwndCheckbut, BM_GETCHECK, 0, 0) == BST_UNCHECKED))
141  return GDT_NONE;
142 
143  *systime = infoPtr->date;
144 
145  return GDT_VALID;
146 }
147 
148 /* Checks value is within configured date range
149  *
150  * PARAMETERS
151  *
152  * [I] infoPtr : valid pointer to control data
153  * [I] date : pointer to valid date data to check
154  *
155  * RETURN VALUE
156  *
157  * TRUE - date within configured range
158  * FALSE - date is outside configured range
159  */
161 {
162  SYSTEMTIME range[2];
163  DWORD limits;
164 
165  if ((MONTHCAL_CompareSystemTime(date, &max_allowed_date) == 1) ||
166  (MONTHCAL_CompareSystemTime(date, &min_allowed_date) == -1))
167  return FALSE;
168 
169  limits = SendMessageW (infoPtr->hMonthCal, MCM_GETRANGE, 0, (LPARAM)range);
170 
171  if (limits & GDTR_MAX)
172  {
173  if (MONTHCAL_CompareSystemTime(date, &range[1]) == 1)
174  return FALSE;
175  }
176 
177  if (limits & GDTR_MIN)
178  {
179  if (MONTHCAL_CompareSystemTime(date, &range[0]) == -1)
180  return FALSE;
181  }
182 
183  return TRUE;
184 }
185 
186 static BOOL
188 {
189  if (!systime) return FALSE;
190 
191  TRACE("%04d/%02d/%02d %02d:%02d:%02d\n",
192  systime->wYear, systime->wMonth, systime->wDay,
193  systime->wHour, systime->wMinute, systime->wSecond);
194 
195  if (flag == GDT_VALID) {
196  if (systime->wYear == 0 ||
197  systime->wMonth < 1 || systime->wMonth > 12 ||
198  systime->wDay < 1 ||
199  systime->wDay > MONTHCAL_MonthLength(systime->wMonth, systime->wYear) ||
200  systime->wHour > 23 ||
201  systime->wMinute > 59 ||
202  systime->wSecond > 59 ||
203  systime->wMilliseconds > 999
204  )
205  return FALSE;
206 
207  /* Windows returns true if the date is valid but outside the limits set */
208  if (!DATETIME_IsDateInValidRange(infoPtr, systime))
209  return TRUE;
210 
211  infoPtr->dateValid = TRUE;
212  infoPtr->date = *systime;
213  /* always store a valid day of week */
215 
216  SendMessageW (infoPtr->hMonthCal, MCM_SETCURSEL, 0, (LPARAM)(&infoPtr->date));
218  } else if ((infoPtr->dwStyle & DTS_SHOWNONE) && (flag == GDT_NONE)) {
219  infoPtr->dateValid = FALSE;
221  }
222  else
223  return FALSE;
224 
225  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
226  return TRUE;
227 }
228 
229 
230 /***
231  * Split up a formattxt in actions.
232  * See ms documentation for the meaning of the letter codes/'specifiers'.
233  *
234  * Notes:
235  * *'dddddd' is handled as 'dddd' plus 'dd'.
236  * *unrecognized formats are strings (here given the type DT_STRING;
237  * start of the string is encoded in lower bits of DT_STRING.
238  * Therefore, 'string' ends finally up as '<show seconds>tring'.
239  *
240  */
241 static void
243 {
244  unsigned int i;
245  int j, k, len;
246  BOOL inside_literal = FALSE; /* inside '...' */
247  int *nrFields = &infoPtr->nrFields;
248 
249  *nrFields = 0;
250  infoPtr->fieldspec[*nrFields] = 0;
252  k = 0;
253 
254  for (i = 0; formattxt[i]; i++) {
255  TRACE ("\n%d %c:", i, formattxt[i]);
256  if (!inside_literal) {
257  for (j = 0; j < len; j++) {
258  if (allowedformatchars[j]==formattxt[i]) {
259  TRACE ("%c[%d,%x]", allowedformatchars[j], *nrFields, infoPtr->fieldspec[*nrFields]);
260  if ((*nrFields==0) && (infoPtr->fieldspec[*nrFields]==0)) {
261  infoPtr->fieldspec[*nrFields] = (j<<4) + 1;
262  break;
263  }
264  if (infoPtr->fieldspec[*nrFields] >> 4 != j) {
265  (*nrFields)++;
266  infoPtr->fieldspec[*nrFields] = (j<<4) + 1;
267  break;
268  }
269  if ((infoPtr->fieldspec[*nrFields] & 0x0f) == maxrepetition[j]) {
270  (*nrFields)++;
271  infoPtr->fieldspec[*nrFields] = (j<<4) + 1;
272  break;
273  }
274  infoPtr->fieldspec[*nrFields]++;
275  break;
276  } /* if allowedformatchar */
277  } /* for j */
278  }
279  else
280  j = len;
281 
282  if (formattxt[i] == '\'')
283  {
284  inside_literal = !inside_literal;
285  continue;
286  }
287 
288  /* char is not a specifier: handle char like a string */
289  if (j == len) {
290  if ((*nrFields==0) && (infoPtr->fieldspec[*nrFields]==0)) {
291  infoPtr->fieldspec[*nrFields] = DT_STRING + k;
292  infoPtr->buflen[*nrFields] = 0;
293  } else if ((infoPtr->fieldspec[*nrFields] & DT_STRING) != DT_STRING) {
294  (*nrFields)++;
295  infoPtr->fieldspec[*nrFields] = DT_STRING + k;
296  infoPtr->buflen[*nrFields] = 0;
297  }
298  infoPtr->textbuf[k] = formattxt[i];
299  k++;
300  infoPtr->buflen[*nrFields]++;
301  } /* if j=len */
302 
303  if (*nrFields == infoPtr->nrFieldsAllocated) {
304  FIXME ("out of memory; should reallocate. crash ahead.\n");
305  }
306  } /* for i */
307 
308  TRACE("\n");
309 
310  if (infoPtr->fieldspec[*nrFields] != 0) (*nrFields)++;
311 }
312 
313 
314 static BOOL
316 {
317  WCHAR format_buf[80];
318 
319  if (!format) {
320  DWORD format_item;
321 
322  if (infoPtr->dwStyle & DTS_LONGDATEFORMAT)
323  format_item = LOCALE_SLONGDATE;
324  else if ((infoPtr->dwStyle & DTS_TIMEFORMAT) == DTS_TIMEFORMAT)
325  format_item = LOCALE_STIMEFORMAT;
326  else /* DTS_SHORTDATEFORMAT */
327  format_item = LOCALE_SSHORTDATE;
328  GetLocaleInfoW(LOCALE_USER_DEFAULT, format_item, format_buf, sizeof(format_buf)/sizeof(format_buf[0]));
329  format = format_buf;
330  }
331 
332  DATETIME_UseFormat (infoPtr, format);
333  InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
334 
335  return TRUE;
336 }
337 
338 
339 static BOOL
341 {
342  if (lpszFormat) {
343  BOOL retval;
344  INT len = MultiByteToWideChar(CP_ACP, 0, lpszFormat, -1, NULL, 0);
345  LPWSTR wstr = Alloc(len * sizeof(WCHAR));
346  if (wstr) MultiByteToWideChar(CP_ACP, 0, lpszFormat, -1, wstr, len);
347  retval = DATETIME_SetFormatW (infoPtr, wstr);
348  Free (wstr);
349  return retval;
350  }
351  else
352  return DATETIME_SetFormatW (infoPtr, 0);
353 
354 }
355 
356 
357 static void
358 DATETIME_ReturnTxt (const DATETIME_INFO *infoPtr, int count, LPWSTR result, int resultSize)
359 {
360  static const WCHAR fmt_dW[] = { '%', 'd', 0 };
361  static const WCHAR fmt__2dW[] = { '%', '.', '2', 'd', 0 };
362  static const WCHAR fmt__3sW[] = { '%', '.', '3', 's', 0 };
363  SYSTEMTIME date = infoPtr->date;
364  int spec;
365  WCHAR buffer[80];
366 
367  *result=0;
368  TRACE ("%d,%d\n", infoPtr->nrFields, count);
369  if (count>infoPtr->nrFields || count < 0) {
370  WARN ("buffer overrun, have %d want %d\n", infoPtr->nrFields, count);
371  return;
372  }
373 
374  if (!infoPtr->fieldspec) return;
375 
376  spec = infoPtr->fieldspec[count];
377  if (spec & DT_STRING) {
378  int txtlen = infoPtr->buflen[count];
379 
380  if (txtlen > resultSize)
381  txtlen = resultSize - 1;
382  memcpy (result, infoPtr->textbuf + (spec &~ DT_STRING), txtlen * sizeof(WCHAR));
383  result[txtlen] = 0;
384  TRACE ("arg%d=%x->[%s]\n", count, infoPtr->fieldspec[count], debugstr_w(result));
385  return;
386  }
387 
388 
389  switch (spec) {
390  case DT_END_FORMAT:
391  *result = 0;
392  break;
393  case ONEDIGITDAY:
394  wsprintfW (result, fmt_dW, date.wDay);
395  break;
396  case TWODIGITDAY:
397  wsprintfW (result, fmt__2dW, date.wDay);
398  break;
399  case THREECHARDAY:
401  /*wsprintfW (result,"%.3s",days[date.wDayOfWeek]);*/
402  break;
403  case FULLDAY:
404  GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDAYNAME1+(date.wDayOfWeek+6)%7, result, resultSize);
405  break;
406  case ONEDIGIT12HOUR:
407  if (date.wHour == 0) {
408  result[0] = '1';
409  result[1] = '2';
410  result[2] = 0;
411  }
412  else
413  wsprintfW (result, fmt_dW, date.wHour - (date.wHour > 12 ? 12 : 0));
414  break;
415  case TWODIGIT12HOUR:
416  if (date.wHour == 0) {
417  result[0] = '1';
418  result[1] = '2';
419  result[2] = 0;
420  }
421  else
422  wsprintfW (result, fmt__2dW, date.wHour - (date.wHour > 12 ? 12 : 0));
423  break;
424  case ONEDIGIT24HOUR:
425  wsprintfW (result, fmt_dW, date.wHour);
426  break;
427  case TWODIGIT24HOUR:
428  wsprintfW (result, fmt__2dW, date.wHour);
429  break;
430  case ONEDIGITSECOND:
431  wsprintfW (result, fmt_dW, date.wSecond);
432  break;
433  case TWODIGITSECOND:
434  wsprintfW (result, fmt__2dW, date.wSecond);
435  break;
436  case ONEDIGITMINUTE:
437  wsprintfW (result, fmt_dW, date.wMinute);
438  break;
439  case TWODIGITMINUTE:
440  wsprintfW (result, fmt__2dW, date.wMinute);
441  break;
442  case ONEDIGITMONTH:
443  wsprintfW (result, fmt_dW, date.wMonth);
444  break;
445  case TWODIGITMONTH:
446  wsprintfW (result, fmt__2dW, date.wMonth);
447  break;
448  case THREECHARMONTH:
450  buffer, sizeof(buffer)/sizeof(buffer[0]));
451  wsprintfW (result, fmt__3sW, buffer);
452  break;
453  case FULLMONTH:
455  result, resultSize);
456  break;
457  case ONELETTERAMPM:
458  result[0] = (date.wHour < 12 ? 'A' : 'P');
459  result[1] = 0;
460  break;
461  case TWOLETTERAMPM:
462  result[0] = (date.wHour < 12 ? 'A' : 'P');
463  result[1] = 'M';
464  result[2] = 0;
465  break;
466  case FORMATCALLBACK:
467  FIXME ("Not implemented\n");
468  result[0] = 'x';
469  result[1] = 0;
470  break;
471  case ONEDIGITYEAR:
472  wsprintfW (result, fmt_dW, date.wYear-10* (int) floor(date.wYear/10));
473  break;
474  case TWODIGITYEAR:
475  wsprintfW (result, fmt__2dW, date.wYear-100* (int) floor(date.wYear/100));
476  break;
477  case INVALIDFULLYEAR:
478  case FULLYEAR:
479  wsprintfW (result, fmt_dW, date.wYear);
480  break;
481  }
482 
483  TRACE ("arg%d=%x->[%s]\n", count, infoPtr->fieldspec[count], debugstr_w(result));
484 }
485 
486 static int wrap(int val, int delta, int minVal, int maxVal)
487 {
488  val += delta;
489  if (delta == INT_MIN || val < minVal) return maxVal;
490  if (delta == INT_MAX || val > maxVal) return minVal;
491  return val;
492 }
493 
494 static void
495 DATETIME_IncreaseField (DATETIME_INFO *infoPtr, int number, int delta)
496 {
497  SYSTEMTIME *date = &infoPtr->date;
498  SYSTEMTIME range[2];
499  DWORD limits;
500  BOOL min;
501 
502  TRACE ("%d\n", number);
503  if ((number > infoPtr->nrFields) || (number < 0)) return;
504 
505  if ((infoPtr->fieldspec[number] & DTHT_DATEFIELD) == 0) return;
506 
507  switch (infoPtr->fieldspec[number]) {
508  case ONEDIGITYEAR:
509  case TWODIGITYEAR:
510  case FULLYEAR:
511  if (delta == INT_MIN)
512  date->wYear = 1752;
513  else if (delta == INT_MAX)
514  date->wYear = 9999;
515  else
516  date->wYear = max(min(date->wYear + delta, 9999), 1752);
517 
518  if (date->wDay > MONTHCAL_MonthLength(date->wMonth, date->wYear))
519  /* This can happen when moving away from a leap year. */
520  date->wDay = MONTHCAL_MonthLength(date->wMonth, date->wYear);
522  break;
523  case ONEDIGITMONTH:
524  case TWODIGITMONTH:
525  case THREECHARMONTH:
526  case FULLMONTH:
527  date->wMonth = wrap(date->wMonth, delta, 1, 12);
529  delta = 0;
530  /* fall through */
531  case ONEDIGITDAY:
532  case TWODIGITDAY:
533  case THREECHARDAY:
534  case FULLDAY:
535  date->wDay = wrap(date->wDay, delta, 1, MONTHCAL_MonthLength(date->wMonth, date->wYear));
537  break;
538  case ONELETTERAMPM:
539  case TWOLETTERAMPM:
540  delta *= 12;
541  /* fall through */
542  case ONEDIGIT12HOUR:
543  case TWODIGIT12HOUR:
544  case ONEDIGIT24HOUR:
545  case TWODIGIT24HOUR:
546  date->wHour = wrap(date->wHour, delta, 0, 23);
547  break;
548  case ONEDIGITMINUTE:
549  case TWODIGITMINUTE:
550  date->wMinute = wrap(date->wMinute, delta, 0, 59);
551  break;
552  case ONEDIGITSECOND:
553  case TWODIGITSECOND:
554  date->wSecond = wrap(date->wSecond, delta, 0, 59);
555  break;
556  case FORMATCALLBACK:
557  FIXME ("Not implemented\n");
558  break;
559  }
560 
561  /* FYI: On 1752/9/14 the calendar changed and England and the
562  * American colonies changed to the Gregorian calendar. This change
563  * involved having September 14th follow September 2nd. So no date
564  * algorithm works before that date.
565  */
566  if (10000 * date->wYear + 100 * date->wMonth + date->wDay < 17520914) {
567  date->wYear = 1752;
568  date->wMonth = 9;
569  date->wDay = 14;
570  date->wSecond = 0;
571  date->wMinute = 0;
572  date->wHour = 0;
573  }
574 
575  /* Ensure time is within bounds */
576  limits = SendMessageW (infoPtr->hMonthCal, MCM_GETRANGE, 0, (LPARAM)range);
577  min = delta < 0;
578 
579  if (limits & (min ? GDTR_MIN : GDTR_MAX))
580  {
581  int i = (min ? 0 : 1);
582 
583  if (MONTHCAL_CompareSystemTime(date, &range[i]) == (min ? -1 : 1))
584  {
585  date->wYear = range[i].wYear;
586  date->wMonth = range[i].wMonth;
587  date->wDayOfWeek = range[i].wDayOfWeek;
588  date->wDay = range[i].wDay;
589  date->wHour = range[i].wHour;
590  date->wMinute = range[i].wMinute;
591  date->wSecond = range[i].wSecond;
592  date->wMilliseconds = range[i].wMilliseconds;
593  }
594  }
595 }
596 
597 static void
599 {
600  /* fields are a fixed width, determined by the largest possible string */
601  /* presumably, these widths should be language dependent */
602  static const WCHAR fld_d1W[] = { '2', 0 };
603  static const WCHAR fld_d2W[] = { '2', '2', 0 };
604  static const WCHAR fld_d4W[] = { '2', '2', '2', '2', 0 };
605  static const WCHAR fld_am1[] = { 'A', 0 };
606  static const WCHAR fld_am2[] = { 'A', 'M', 0 };
607  int spec;
608  WCHAR buffer[80];
609  LPCWSTR bufptr;
610  SIZE size;
611 
612  TRACE ("%d,%d\n", infoPtr->nrFields, count);
613  if (count>infoPtr->nrFields || count < 0) {
614  WARN ("buffer overrun, have %d want %d\n", infoPtr->nrFields, count);
615  return;
616  }
617 
618  if (!infoPtr->fieldspec) return;
619 
620  spec = infoPtr->fieldspec[count];
621  if (spec & DT_STRING) {
622  int txtlen = infoPtr->buflen[count];
623 
624  if (txtlen > 79)
625  txtlen = 79;
626  memcpy (buffer, infoPtr->textbuf + (spec &~ DT_STRING), txtlen * sizeof(WCHAR));
627  buffer[txtlen] = 0;
628  bufptr = buffer;
629  }
630  else {
631  switch (spec) {
632  case ONEDIGITDAY:
633  case ONEDIGIT12HOUR:
634  case ONEDIGIT24HOUR:
635  case ONEDIGITSECOND:
636  case ONEDIGITMINUTE:
637  case ONEDIGITMONTH:
638  case ONEDIGITYEAR:
639  /* these seem to use a two byte field */
640  case TWODIGITDAY:
641  case TWODIGIT12HOUR:
642  case TWODIGIT24HOUR:
643  case TWODIGITSECOND:
644  case TWODIGITMINUTE:
645  case TWODIGITMONTH:
646  case TWODIGITYEAR:
647  bufptr = fld_d2W;
648  break;
649  case INVALIDFULLYEAR:
650  case FULLYEAR:
651  bufptr = fld_d4W;
652  break;
653  case THREECHARMONTH:
654  case FULLMONTH:
655  case THREECHARDAY:
656  case FULLDAY:
657  {
658  static const WCHAR fld_day[] = {'W','e','d','n','e','s','d','a','y',0};
659  static const WCHAR fld_abbrday[] = {'W','e','d',0};
660  static const WCHAR fld_mon[] = {'S','e','p','t','e','m','b','e','r',0};
661  static const WCHAR fld_abbrmon[] = {'D','e','c',0};
662 
663  const WCHAR *fall;
664  LCTYPE lctype;
665  INT i, max_count;
666  LONG cx;
667 
668  /* choose locale data type and fallback string */
669  switch (spec) {
670  case THREECHARDAY:
671  fall = fld_abbrday;
672  lctype = LOCALE_SABBREVDAYNAME1;
673  max_count = 7;
674  break;
675  case FULLDAY:
676  fall = fld_day;
677  lctype = LOCALE_SDAYNAME1;
678  max_count = 7;
679  break;
680  case THREECHARMONTH:
681  fall = fld_abbrmon;
682  lctype = LOCALE_SABBREVMONTHNAME1;
683  max_count = 12;
684  break;
685  default: /* FULLMONTH */
686  fall = fld_mon;
687  lctype = LOCALE_SMONTHNAME1;
688  max_count = 12;
689  break;
690  }
691 
692  cx = 0;
693  for (i = 0; i < max_count; i++)
694  {
695  if(GetLocaleInfoW(LOCALE_USER_DEFAULT, lctype + i,
696  buffer, lstrlenW(buffer)))
697  {
698  GetTextExtentPoint32W(hdc, buffer, lstrlenW(buffer), &size);
699  if (size.cx > cx) cx = size.cx;
700  }
701  else /* locale independent fallback on failure */
702  {
703  GetTextExtentPoint32W(hdc, fall, lstrlenW(fall), &size);
704  cx = size.cx;
705  break;
706  }
707  }
708  *width = cx;
709  return;
710  }
711  case ONELETTERAMPM:
712  bufptr = fld_am1;
713  break;
714  case TWOLETTERAMPM:
715  bufptr = fld_am2;
716  break;
717  default:
718  bufptr = fld_d1W;
719  break;
720  }
721  }
722  GetTextExtentPoint32W (hdc, bufptr, strlenW(bufptr), &size);
723  *width = size.cx;
724 }
725 
726 static void
728 {
729  TRACE("\n");
730 
731  if (infoPtr->dateValid) {
732  int i, prevright;
733  RECT *field;
734  RECT *rcDraw = &infoPtr->rcDraw;
735  SIZE size;
736  COLORREF oldTextColor;
737  SHORT fieldWidth = 0;
738  HFONT oldFont = SelectObject (hdc, infoPtr->hFont);
739  INT oldBkMode = SetBkMode (hdc, TRANSPARENT);
740  WCHAR txt[80];
741 
742  DATETIME_ReturnTxt (infoPtr, 0, txt, sizeof(txt)/sizeof(txt[0]));
743  GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size);
744  rcDraw->bottom = size.cy + 2;
745 
746  prevright = infoPtr->checkbox.right = ((infoPtr->dwStyle & DTS_SHOWNONE) ? 18 : 2);
747 
748  for (i = 0; i < infoPtr->nrFields; i++) {
749  DATETIME_ReturnTxt (infoPtr, i, txt, sizeof(txt)/sizeof(txt[0]));
750  GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size);
751  DATETIME_ReturnFieldWidth (infoPtr, hdc, i, &fieldWidth);
752  field = &infoPtr->fieldRect[i];
753  field->left = prevright;
754  field->right = prevright + fieldWidth;
755  field->top = rcDraw->top;
756  field->bottom = rcDraw->bottom;
757  prevright = field->right;
758 
759  if (infoPtr->dwStyle & WS_DISABLED)
760  oldTextColor = SetTextColor (hdc, comctl32_color.clrGrayText);
761  else if ((infoPtr->haveFocus) && (i == infoPtr->select)) {
762  RECT selection;
763 
764  /* fill if focused */
766 
767  if (infoPtr->nCharsEntered)
768  {
769  memcpy(txt, infoPtr->charsEntered, infoPtr->nCharsEntered * sizeof(WCHAR));
770  txt[infoPtr->nCharsEntered] = 0;
771  GetTextExtentPoint32W (hdc, txt, strlenW(txt), &size);
772  }
773 
774  SetRect(&selection, 0, 0, size.cx, size.cy);
775  /* center rectangle */
776  OffsetRect(&selection, (field->right + field->left - size.cx)/2,
777  (field->bottom - size.cy)/2);
778 
779  FillRect(hdc, &selection, hbr);
780  DeleteObject (hbr);
781  oldTextColor = SetTextColor (hdc, comctl32_color.clrWindow);
782  }
783  else
784  oldTextColor = SetTextColor (hdc, comctl32_color.clrWindowText);
785 
786  /* draw the date text using the colour set above */
787  DrawTextW (hdc, txt, strlenW(txt), field, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
788  SetTextColor (hdc, oldTextColor);
789  }
790  SetBkMode (hdc, oldBkMode);
791  SelectObject (hdc, oldFont);
792  }
793 
794  if (!(infoPtr->dwStyle & DTS_UPDOWN)) {
795  DrawFrameControl(hdc, &infoPtr->calbutton, DFC_SCROLL,
796  DFCS_SCROLLDOWN | (infoPtr->bCalDepressed ? DFCS_PUSHED : 0) |
797  (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
798  }
799 }
800 
801 
802 static INT
804 {
805  int i;
806 
807  TRACE ("%s\n", wine_dbgstr_point(&pt));
808 
809  if (PtInRect (&infoPtr->calbutton, pt)) return DTHT_MCPOPUP;
810  if (PtInRect (&infoPtr->checkbox, pt)) return DTHT_CHECKBOX;
811 
812  for (i = 0; i < infoPtr->nrFields; i++) {
813  if (PtInRect (&infoPtr->fieldRect[i], pt)) return i;
814  }
815 
816  return DTHT_NONE;
817 }
818 
819 /* Returns index of the nearest preceding date field from given,
820  or -1 if none was found */
821 static int DATETIME_GetPrevDateField(const DATETIME_INFO *infoPtr, int i)
822 {
823  for(--i; i >= 0; i--)
824  {
825  if (infoPtr->fieldspec[i] & DTHT_DATEFIELD) return i;
826  }
827  return -1;
828 }
829 
830 static void
832 {
833  int fieldNum = infoPtr->select & DTHT_DATEFIELD;
834  int i, val = 0;
835  BOOL clamp_day = FALSE;
836  SYSTEMTIME date = infoPtr->date;
837  int oldyear;
838 
839  if (infoPtr->select == -1 || infoPtr->nCharsEntered == 0)
840  return;
841 
842  if ((infoPtr->fieldspec[fieldNum] == ONELETTERAMPM) ||
843  (infoPtr->fieldspec[fieldNum] == TWOLETTERAMPM))
844  val = infoPtr->charsEntered[0];
845  else {
846  for (i=0; i<infoPtr->nCharsEntered; i++)
847  val = val * 10 + infoPtr->charsEntered[i] - '0';
848  }
849 
850  infoPtr->nCharsEntered = 0;
851 
852  switch (infoPtr->fieldspec[fieldNum]) {
853  case ONEDIGITYEAR:
854  case TWODIGITYEAR:
855  oldyear = date.wYear;
856  date.wYear = date.wYear - (date.wYear%100) + val;
857 
858  if (DATETIME_IsDateInValidRange(infoPtr, &date))
859  clamp_day = TRUE;
860  else
861  date.wYear = oldyear;
862 
863  break;
864  case INVALIDFULLYEAR:
865  case FULLYEAR:
866  oldyear = date.wYear;
867  date.wYear = val;
868 
869  if (DATETIME_IsDateInValidRange(infoPtr, &date))
870  clamp_day = TRUE;
871  else
872  date.wYear = oldyear;
873 
874  break;
875  case ONEDIGITMONTH:
876  case TWODIGITMONTH:
877  date.wMonth = val;
878  clamp_day = TRUE;
879  break;
880  case ONEDIGITDAY:
881  case TWODIGITDAY:
882  date.wDay = val;
883  break;
884  case ONEDIGIT12HOUR:
885  case TWODIGIT12HOUR:
886  if (val >= 24)
887  val -= 20;
888 
889  if (val >= 13)
890  date.wHour = val;
891  else if (val != 0) {
892  if (date.wHour >= 12) /* preserve current AM/PM state */
893  date.wHour = (val == 12 ? 12 : val + 12);
894  else
895  date.wHour = (val == 12 ? 0 : val);
896  }
897  break;
898  case ONEDIGIT24HOUR:
899  case TWODIGIT24HOUR:
900  date.wHour = val;
901  break;
902  case ONEDIGITMINUTE:
903  case TWODIGITMINUTE:
904  date.wMinute = val;
905  break;
906  case ONEDIGITSECOND:
907  case TWODIGITSECOND:
908  date.wSecond = val;
909  break;
910  case ONELETTERAMPM:
911  case TWOLETTERAMPM:
912  if (val == 'a' || val == 'A') {
913  if (date.wHour >= 12)
914  date.wHour -= 12;
915  } else if (val == 'p' || val == 'P') {
916  if (date.wHour < 12)
917  date.wHour += 12;
918  }
919  break;
920  }
921 
922  if (clamp_day && date.wDay > MONTHCAL_MonthLength(date.wMonth, date.wYear))
923  date.wDay = MONTHCAL_MonthLength(date.wMonth, date.wYear);
924 
925  if (DATETIME_SetSystemTime(infoPtr, GDT_VALID, &date))
927 }
928 
929 static void
931 {
933 
934  infoPtr->select = select;
935  infoPtr->nCharsEntered = 0;
936 }
937 
938 static LRESULT
940 {
941  POINT pt;
942  int new;
943 
944  pt.x = x;
945  pt.y = y;
946  new = DATETIME_HitTest (infoPtr, pt);
947 
948  SetFocus(infoPtr->hwndSelf);
949 
950  if (!(new & DTHT_NODATEMASK) || (new == DTHT_NONE))
951  {
952  if (new == DTHT_NONE)
953  new = infoPtr->nrFields - 1;
954  else
955  {
956  /* hitting string part moves selection to next date field to left */
957  if (infoPtr->fieldspec[new] & DT_STRING)
958  {
959  new = DATETIME_GetPrevDateField(infoPtr, new);
960  if (new == -1) return 0;
961  }
962  /* never select full day of week */
963  if (infoPtr->fieldspec[new] == FULLDAY) return 0;
964  }
965  }
966 
967  DATETIME_SetSelectedField(infoPtr, new);
968 
969  if (infoPtr->select == DTHT_MCPOPUP) {
970  RECT rcMonthCal;
971  POINT pos;
972  SendMessageW(infoPtr->hMonthCal, MCM_GETMINREQRECT, 0, (LPARAM)&rcMonthCal);
973 
974  /* FIXME: button actually is only depressed during dropdown of the */
975  /* calendar control and when the mouse is over the button window */
976  infoPtr->bCalDepressed = TRUE;
977 
978  /* recalculate the position of the monthcal popup */
979  if(infoPtr->dwStyle & DTS_RIGHTALIGN)
980  pos.x = infoPtr->calbutton.left - (rcMonthCal.right - rcMonthCal.left);
981  else
982  /* FIXME: this should be after the area reserved for the checkbox */
983  pos.x = infoPtr->rcDraw.left;
984 
985  pos.y = infoPtr->rcClient.bottom;
986  OffsetRect( &rcMonthCal, pos.x, pos.y );
987  MapWindowPoints( infoPtr->hwndSelf, 0, (POINT *)&rcMonthCal, 2 );
988  SetWindowPos(infoPtr->hMonthCal, 0, rcMonthCal.left, rcMonthCal.top,
989  rcMonthCal.right - rcMonthCal.left, rcMonthCal.bottom - rcMonthCal.top, 0);
990 
991  if(IsWindowVisible(infoPtr->hMonthCal)) {
992  ShowWindow(infoPtr->hMonthCal, SW_HIDE);
993  infoPtr->bDropdownEnabled = FALSE;
995  } else {
996  const SYSTEMTIME *lprgSysTimeArray = &infoPtr->date;
997  TRACE("update calendar %04d/%02d/%02d\n",
998  lprgSysTimeArray->wYear, lprgSysTimeArray->wMonth, lprgSysTimeArray->wDay);
999  SendMessageW(infoPtr->hMonthCal, MCM_SETCURSEL, 0, (LPARAM)(&infoPtr->date));
1000 
1001  if (infoPtr->bDropdownEnabled) {
1002  ShowWindow(infoPtr->hMonthCal, SW_SHOW);
1004  }
1005  infoPtr->bDropdownEnabled = TRUE;
1006  }
1007 
1008  TRACE ("dt:%p mc:%p mc parent:%p, desktop:%p\n",
1009  infoPtr->hwndSelf, infoPtr->hMonthCal, infoPtr->hwndNotify, GetDesktopWindow ());
1010  }
1011 
1012  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
1013 
1014  return 0;
1015 }
1016 
1017 
1018 static LRESULT
1020 {
1021  if(infoPtr->bCalDepressed) {
1022  infoPtr->bCalDepressed = FALSE;
1023  InvalidateRect(infoPtr->hwndSelf, &(infoPtr->calbutton), TRUE);
1024  }
1025 
1026  return 0;
1027 }
1028 
1029 
1030 static LRESULT
1032 {
1033  if (!hdc) {
1034  PAINTSTRUCT ps;
1035  hdc = BeginPaint (infoPtr->hwndSelf, &ps);
1036  DATETIME_Refresh (infoPtr, hdc);
1037  EndPaint (infoPtr->hwndSelf, &ps);
1038  } else {
1039  DATETIME_Refresh (infoPtr, hdc);
1040  }
1041 
1042  /* Not a click on the dropdown box, enabled it */
1043  infoPtr->bDropdownEnabled = TRUE;
1044 
1045  return 0;
1046 }
1047 
1048 
1049 static LRESULT
1051 {
1052  if( HIWORD(wParam) == BN_CLICKED) {
1053  DWORD state = SendMessageW((HWND)lParam, BM_GETCHECK, 0, 0);
1054  infoPtr->dateValid = (state == BST_CHECKED);
1055  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
1056  }
1057  return 0;
1058 }
1059 
1060 
1061 
1062 static LRESULT
1064 {
1065  TRACE("hwndbutton = %p\n", infoPtr->hwndCheckbut);
1066  if(infoPtr->hwndCheckbut == (HWND)lParam)
1067  return DATETIME_Button_Command(infoPtr, wParam, lParam);
1068  return 0;
1069 }
1070 
1071 
1072 static LRESULT
1074 {
1075  TRACE("%p %s\n", infoPtr, bEnable ? "TRUE" : "FALSE");
1076  if (bEnable)
1077  infoPtr->dwStyle &= ~WS_DISABLED;
1078  else
1079  infoPtr->dwStyle |= WS_DISABLED;
1080 
1081  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
1082 
1083  return 0;
1084 }
1085 
1086 
1087 static LRESULT
1089 {
1090  HBRUSH hBrush, hSolidBrush = NULL;
1091  RECT rc;
1092 
1093  if (infoPtr->dwStyle & WS_DISABLED)
1094  hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrBtnFace);
1095  else
1096  {
1097  hBrush = (HBRUSH)SendMessageW(infoPtr->hwndNotify, WM_CTLCOLOREDIT,
1098  (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf);
1099  if (!hBrush)
1100  hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrWindow);
1101  }
1102 
1103  GetClientRect (infoPtr->hwndSelf, &rc);
1104 
1105  FillRect (hdc, &rc, hBrush);
1106 
1107  if (hSolidBrush)
1108  DeleteObject(hSolidBrush);
1109 
1110  return -1;
1111 }
1112 
1113 
1114 static LRESULT
1115 DATETIME_Notify (DATETIME_INFO *infoPtr, const NMHDR *lpnmh)
1116 {
1117  TRACE ("Got notification %x from %p\n", lpnmh->code, lpnmh->hwndFrom);
1118  TRACE ("info: %p %p %p\n", infoPtr->hwndSelf, infoPtr->hMonthCal, infoPtr->hUpdown);
1119 
1120  if (lpnmh->code == MCN_SELECT) {
1121  ShowWindow(infoPtr->hMonthCal, SW_HIDE);
1122  infoPtr->dateValid = TRUE;
1123  SendMessageW (infoPtr->hMonthCal, MCM_GETCURSEL, 0, (LPARAM)&infoPtr->date);
1124  TRACE("got from calendar %04d/%02d/%02d day of week %d\n",
1125  infoPtr->date.wYear, infoPtr->date.wMonth, infoPtr->date.wDay, infoPtr->date.wDayOfWeek);
1127  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
1130  }
1131  if ((lpnmh->hwndFrom == infoPtr->hUpdown) && (lpnmh->code == UDN_DELTAPOS)) {
1132  const NM_UPDOWN *lpnmud = (const NM_UPDOWN*)lpnmh;
1133  TRACE("Delta pos %d\n", lpnmud->iDelta);
1134  infoPtr->pendingUpdown = lpnmud->iDelta;
1135  }
1136  return 0;
1137 }
1138 
1139 
1140 static LRESULT
1142 {
1143  int fieldNum = infoPtr->select & DTHT_DATEFIELD;
1144  int wrap = 0;
1145  int new;
1146 
1147  if (!(infoPtr->haveFocus)) return 0;
1148  if ((fieldNum==0) && (infoPtr->select)) return 0;
1149 
1150  if (infoPtr->select & FORMATCALLMASK) {
1151  FIXME ("Callbacks not implemented yet\n");
1152  }
1153 
1154  switch (vkCode) {
1155  case VK_ADD:
1156  case VK_UP:
1157  infoPtr->nCharsEntered = 0;
1158  DATETIME_IncreaseField (infoPtr, fieldNum, 1);
1160  break;
1161  case VK_SUBTRACT:
1162  case VK_DOWN:
1163  infoPtr->nCharsEntered = 0;
1164  DATETIME_IncreaseField (infoPtr, fieldNum, -1);
1166  break;
1167  case VK_HOME:
1168  infoPtr->nCharsEntered = 0;
1169  DATETIME_IncreaseField (infoPtr, fieldNum, INT_MIN);
1171  break;
1172  case VK_END:
1173  infoPtr->nCharsEntered = 0;
1174  DATETIME_IncreaseField (infoPtr, fieldNum, INT_MAX);
1176  break;
1177  case VK_LEFT:
1178  new = infoPtr->select;
1179  do {
1180  if (new == 0) {
1181  new = new - 1;
1182  wrap++;
1183  } else {
1184  new--;
1185  }
1186  } while ((infoPtr->fieldspec[new] & DT_STRING) && (wrap<2));
1187  if (new != infoPtr->select)
1188  DATETIME_SetSelectedField(infoPtr, new);
1189  break;
1190  case VK_RIGHT:
1191  new = infoPtr->select;
1192  do {
1193  new++;
1194  if (new==infoPtr->nrFields) {
1195  new = 0;
1196  wrap++;
1197  }
1198  } while ((infoPtr->fieldspec[new] & DT_STRING) && (wrap<2));
1199  if (new != infoPtr->select)
1200  DATETIME_SetSelectedField(infoPtr, new);
1201  break;
1202  }
1203 
1204  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
1205 
1206  return 0;
1207 }
1208 
1209 
1210 static LRESULT
1212 {
1213  int fieldNum, fieldSpec;
1214 
1215  fieldNum = infoPtr->select & DTHT_DATEFIELD;
1216  fieldSpec = infoPtr->fieldspec[fieldNum];
1217 
1218  if (fieldSpec == ONELETTERAMPM || fieldSpec == TWOLETTERAMPM) {
1219  infoPtr->charsEntered[0] = vkCode;
1220  infoPtr->nCharsEntered = 1;
1221 
1222  DATETIME_ApplySelectedField(infoPtr);
1223  } else if (vkCode >= '0' && vkCode <= '9') {
1224  int maxChars;
1225 
1226  infoPtr->charsEntered[infoPtr->nCharsEntered++] = vkCode;
1227 
1228  if (fieldSpec == INVALIDFULLYEAR || fieldSpec == FULLYEAR)
1229  maxChars = 4;
1230  else
1231  maxChars = 2;
1232 
1233  if ((fieldSpec == ONEDIGIT12HOUR ||
1234  fieldSpec == TWODIGIT12HOUR ||
1235  fieldSpec == ONEDIGIT24HOUR ||
1236  fieldSpec == TWODIGIT24HOUR) &&
1237  (infoPtr->nCharsEntered == 1))
1238  {
1239  if (vkCode >= '3')
1240  maxChars = 1;
1241  }
1242 
1243  if (maxChars == infoPtr->nCharsEntered)
1244  DATETIME_ApplySelectedField(infoPtr);
1245  }
1246 
1247  return 0;
1248 }
1249 
1250 
1251 static LRESULT
1253 {
1254  int fieldNum = infoPtr->select & DTHT_DATEFIELD;
1255 
1256  if ((SHORT)LOWORD(wScroll) != SB_THUMBPOSITION) return 0;
1257  if (!(infoPtr->haveFocus)) return 0;
1258  if ((fieldNum==0) && (infoPtr->select)) return 0;
1259 
1260  if (infoPtr->pendingUpdown >= 0) {
1261  DATETIME_IncreaseField (infoPtr, fieldNum, 1);
1263  }
1264  else {
1265  DATETIME_IncreaseField (infoPtr, fieldNum, -1);
1267  }
1268 
1269  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
1270 
1271  return 0;
1272 }
1273 
1274 
1275 static LRESULT
1277 {
1278  TRACE("lost focus to %p\n", lostFocus);
1279 
1280  if (infoPtr->haveFocus) {
1282  infoPtr->haveFocus = 0;
1283  DATETIME_SetSelectedField (infoPtr, -1);
1284  }
1285 
1286  InvalidateRect (infoPtr->hwndSelf, NULL, TRUE);
1287 
1288  return 0;
1289 }
1290 
1291 
1292 static LRESULT
1294 {
1295  DWORD dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1296  /* force control to have client edge */
1297  dwExStyle |= WS_EX_CLIENTEDGE;
1298  SetWindowLongW(hwnd, GWL_EXSTYLE, dwExStyle);
1299 
1300  return DefWindowProcW(hwnd, WM_NCCREATE, 0, (LPARAM)lpcs);
1301 }
1302 
1303 
1304 static LRESULT
1305 DATETIME_SetFocus (DATETIME_INFO *infoPtr, HWND lostFocus)
1306 {
1307  TRACE("got focus from %p\n", lostFocus);
1308 
1309  /* if monthcal is open and it loses focus, close monthcal */
1310  if (infoPtr->hMonthCal && (lostFocus == infoPtr->hMonthCal) &&
1311  IsWindowVisible(infoPtr->hMonthCal))
1312  {
1313  ShowWindow(infoPtr->hMonthCal, SW_HIDE);
1315  /* note: this get triggered even if monthcal loses focus to a dropdown
1316  * box click, which occurs without an intermediate WM_PAINT call
1317  */
1318  infoPtr->bDropdownEnabled = FALSE;
1319  return 0;
1320  }
1321 
1322  if (infoPtr->haveFocus == 0) {
1324  infoPtr->haveFocus = DTHT_GOTFOCUS;
1325  }
1326 
1327  InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
1328 
1329  return 0;
1330 }
1331 
1332 
1333 static BOOL
1335 {
1336  NMDATETIMECHANGE dtdtc;
1337 
1338  dtdtc.nmhdr.hwndFrom = infoPtr->hwndSelf;
1339  dtdtc.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
1340  dtdtc.nmhdr.code = DTN_DATETIMECHANGE;
1341 
1342  dtdtc.dwFlags = infoPtr->dateValid ? GDT_VALID : GDT_NONE;
1343 
1344  dtdtc.st = infoPtr->date;
1345  return (BOOL) SendMessageW (infoPtr->hwndNotify, WM_NOTIFY,
1346  dtdtc.nmhdr.idFrom, (LPARAM)&dtdtc);
1347 }
1348 
1349 
1350 static BOOL
1352 {
1353  NMHDR nmhdr;
1354 
1355  TRACE("%x\n", code);
1356  nmhdr.hwndFrom = infoPtr->hwndSelf;
1357  nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
1358  nmhdr.code = code;
1359 
1360  return (BOOL) SendMessageW (infoPtr->hwndNotify, WM_NOTIFY,
1361  nmhdr.idFrom, (LPARAM)&nmhdr);
1362 }
1363 
1364 static LRESULT
1366 {
1367  /* set size */
1368  infoPtr->rcClient.bottom = height;
1369  infoPtr->rcClient.right = width;
1370 
1371  TRACE("Height=%d, Width=%d\n", infoPtr->rcClient.bottom, infoPtr->rcClient.right);
1372 
1373  infoPtr->rcDraw = infoPtr->rcClient;
1374 
1375  if (infoPtr->dwStyle & DTS_UPDOWN) {
1376  SetWindowPos(infoPtr->hUpdown, NULL,
1377  infoPtr->rcClient.right-14, 0,
1378  15, infoPtr->rcClient.bottom - infoPtr->rcClient.top,
1380  }
1381  else {
1382  /* set the size of the button that drops the calendar down */
1383  /* FIXME: account for style that allows button on left side */
1384  infoPtr->calbutton.top = infoPtr->rcDraw.top;
1385  infoPtr->calbutton.bottom= infoPtr->rcDraw.bottom;
1386  infoPtr->calbutton.left = infoPtr->rcDraw.right-15;
1387  infoPtr->calbutton.right = infoPtr->rcDraw.right;
1388  }
1389 
1390  /* set enable/disable button size for show none style being enabled */
1391  /* FIXME: these dimensions are completely incorrect */
1392  infoPtr->checkbox.top = infoPtr->rcDraw.top;
1393  infoPtr->checkbox.bottom = infoPtr->rcDraw.bottom;
1394  infoPtr->checkbox.left = infoPtr->rcDraw.left;
1395  infoPtr->checkbox.right = infoPtr->rcDraw.left + 10;
1396 
1397  InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
1398 
1399  return 0;
1400 }
1401 
1402 static LRESULT
1404 {
1405  TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n",
1406  wStyleType, lpss->styleOld, lpss->styleNew);
1407 
1408  /* block DTS_SHOWNONE change */
1409  if ((lpss->styleNew ^ lpss->styleOld) & DTS_SHOWNONE)
1410  {
1411  if (lpss->styleOld & DTS_SHOWNONE)
1412  lpss->styleNew |= DTS_SHOWNONE;
1413  else
1414  lpss->styleNew &= ~DTS_SHOWNONE;
1415  }
1416 
1417  return 0;
1418 }
1419 
1420 static LRESULT
1421 DATETIME_StyleChanged(DATETIME_INFO *infoPtr, WPARAM wStyleType, const STYLESTRUCT *lpss)
1422 {
1423  TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n",
1424  wStyleType, lpss->styleOld, lpss->styleNew);
1425 
1426  if (wStyleType != GWL_STYLE) return 0;
1427 
1428  infoPtr->dwStyle = lpss->styleNew;
1429 
1430  if ( !(lpss->styleOld & DTS_SHOWNONE) && (lpss->styleNew & DTS_SHOWNONE) ) {
1432  2, 2, 13, 13, infoPtr->hwndSelf, 0,
1434  SendMessageW (infoPtr->hwndCheckbut, BM_SETCHECK, infoPtr->dateValid ? 1 : 0, 0);
1435  }
1436  if ( (lpss->styleOld & DTS_SHOWNONE) && !(lpss->styleNew & DTS_SHOWNONE) ) {
1437  DestroyWindow(infoPtr->hwndCheckbut);
1438  infoPtr->hwndCheckbut = 0;
1439  }
1440  if ( !(lpss->styleOld & DTS_UPDOWN) && (lpss->styleNew & DTS_UPDOWN) ) {
1441  infoPtr->hUpdown = CreateUpDownControl (WS_CHILD | WS_BORDER | WS_VISIBLE, 120, 1, 20, 20,
1442  infoPtr->hwndSelf, 1, 0, 0, UD_MAXVAL, UD_MINVAL, 0);
1443  }
1444  if ( (lpss->styleOld & DTS_UPDOWN) && !(lpss->styleNew & DTS_UPDOWN) ) {
1445  DestroyWindow(infoPtr->hUpdown);
1446  infoPtr->hUpdown = 0;
1447  }
1448 
1449  InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
1450  return 0;
1451 }
1452 
1453 
1454 static LRESULT
1455 DATETIME_SetFont (DATETIME_INFO *infoPtr, HFONT font, BOOL repaint)
1456 {
1457  infoPtr->hFont = font;
1458  if (repaint) InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
1459  return 0;
1460 }
1461 
1462 
1463 static LRESULT
1465 {
1466  DATETIME_INFO *infoPtr = Alloc (sizeof(DATETIME_INFO));
1467  STYLESTRUCT ss = { 0, lpcs->style };
1468 
1469  if (!infoPtr) return -1;
1470 
1471  infoPtr->hwndSelf = hwnd;
1472  infoPtr->dwStyle = lpcs->style;
1473 
1474  infoPtr->nrFieldsAllocated = 32;
1475  infoPtr->fieldspec = Alloc (infoPtr->nrFieldsAllocated * sizeof(int));
1476  infoPtr->fieldRect = Alloc (infoPtr->nrFieldsAllocated * sizeof(RECT));
1477  infoPtr->buflen = Alloc (infoPtr->nrFieldsAllocated * sizeof(int));
1478  infoPtr->hwndNotify = lpcs->hwndParent;
1479  infoPtr->select = -1; /* initially, nothing is selected */
1480  infoPtr->bDropdownEnabled = TRUE;
1481 
1482  DATETIME_StyleChanged(infoPtr, GWL_STYLE, &ss);
1483  DATETIME_SetFormatW (infoPtr, 0);
1484 
1485  /* create the monthcal control */
1487  0, 0, 0, 0, infoPtr->hwndSelf, 0, 0, 0);
1488 
1489  /* initialize info structure */
1490  GetLocalTime (&infoPtr->date);
1491  infoPtr->dateValid = TRUE;
1493 
1494  SetWindowLongPtrW (hwnd, 0, (DWORD_PTR)infoPtr);
1495 
1496  return 0;
1497 }
1498 
1499 
1500 
1501 static LRESULT
1503 {
1504  if (infoPtr->hwndCheckbut)
1505  DestroyWindow(infoPtr->hwndCheckbut);
1506  if (infoPtr->hUpdown)
1507  DestroyWindow(infoPtr->hUpdown);
1508  if (infoPtr->hMonthCal)
1509  DestroyWindow(infoPtr->hMonthCal);
1510  SetWindowLongPtrW( infoPtr->hwndSelf, 0, 0 ); /* clear infoPtr */
1511  Free (infoPtr->buflen);
1512  Free (infoPtr->fieldRect);
1513  Free (infoPtr->fieldspec);
1514  Free (infoPtr);
1515  return 0;
1516 }
1517 
1518 
1519 static INT
1521 {
1522  WCHAR buf[80];
1523  int i;
1524 
1525  if (!dst || (count <= 0)) return 0;
1526 
1527  dst[0] = 0;
1528  for (i = 0; i < infoPtr->nrFields; i++)
1529  {
1530  DATETIME_ReturnTxt(infoPtr, i, buf, sizeof(buf)/sizeof(buf[0]));
1531  if ((strlenW(dst) + strlenW(buf)) < count)
1532  strcatW(dst, buf);
1533  else break;
1534  }
1535  return strlenW(dst);
1536 }
1537 
1538 
1539 static LRESULT WINAPI
1541 {
1542  DATETIME_INFO *infoPtr = ((DATETIME_INFO *)GetWindowLongPtrW (hwnd, 0));
1543 
1544  TRACE ("%x, %lx, %lx\n", uMsg, wParam, lParam);
1545 
1546  if (!infoPtr && (uMsg != WM_CREATE) && (uMsg != WM_NCCREATE))
1547  return DefWindowProcW( hwnd, uMsg, wParam, lParam );
1548 
1549  switch (uMsg) {
1550 
1551  case DTM_GETSYSTEMTIME:
1552  return DATETIME_GetSystemTime (infoPtr, (SYSTEMTIME *) lParam);
1553 
1554  case DTM_SETSYSTEMTIME:
1555  return DATETIME_SetSystemTime (infoPtr, wParam, (SYSTEMTIME *) lParam);
1556 
1557  case DTM_GETRANGE:
1558  return SendMessageW (infoPtr->hMonthCal, MCM_GETRANGE, wParam, lParam);
1559 
1560  case DTM_SETRANGE:
1561  return SendMessageW (infoPtr->hMonthCal, MCM_SETRANGE, wParam, lParam);
1562 
1563  case DTM_SETFORMATA:
1564  return DATETIME_SetFormatA (infoPtr, (LPCSTR)lParam);
1565 
1566  case DTM_SETFORMATW:
1567  return DATETIME_SetFormatW (infoPtr, (LPCWSTR)lParam);
1568 
1569  case DTM_GETMONTHCAL:
1570  return (LRESULT)infoPtr->hMonthCal;
1571 
1572  case DTM_SETMCCOLOR:
1573  return SendMessageW (infoPtr->hMonthCal, MCM_SETCOLOR, wParam, lParam);
1574 
1575  case DTM_GETMCCOLOR:
1576  return SendMessageW (infoPtr->hMonthCal, MCM_GETCOLOR, wParam, 0);
1577 
1578  case DTM_SETMCFONT:
1579  return SendMessageW (infoPtr->hMonthCal, WM_SETFONT, wParam, lParam);
1580 
1581  case DTM_GETMCFONT:
1582  return SendMessageW (infoPtr->hMonthCal, WM_GETFONT, wParam, lParam);
1583 
1584  case WM_NOTIFY:
1585  return DATETIME_Notify (infoPtr, (LPNMHDR)lParam);
1586 
1587  case WM_ENABLE:
1588  return DATETIME_Enable (infoPtr, (BOOL)wParam);
1589 
1590  case WM_ERASEBKGND:
1591  return DATETIME_EraseBackground (infoPtr, (HDC)wParam);
1592 
1593  case WM_GETDLGCODE:
1595 
1596  case WM_PRINTCLIENT:
1597  case WM_PAINT:
1598  return DATETIME_Paint (infoPtr, (HDC)wParam);
1599 
1600  case WM_KEYDOWN:
1601  return DATETIME_KeyDown (infoPtr, wParam);
1602 
1603  case WM_CHAR:
1604  return DATETIME_Char (infoPtr, wParam);
1605 
1606  case WM_KILLFOCUS:
1607  return DATETIME_KillFocus (infoPtr, (HWND)wParam);
1608 
1609  case WM_NCCREATE:
1610  return DATETIME_NCCreate (hwnd, (LPCREATESTRUCTW)lParam);
1611 
1612  case WM_SETFOCUS:
1613  return DATETIME_SetFocus (infoPtr, (HWND)wParam);
1614 
1615  case WM_SIZE:
1616  return DATETIME_Size (infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
1617 
1618  case WM_LBUTTONDOWN:
1619  return DATETIME_LButtonDown (infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
1620 
1621  case WM_LBUTTONUP:
1622  return DATETIME_LButtonUp (infoPtr);
1623 
1624  case WM_VSCROLL:
1625  return DATETIME_VScroll (infoPtr, (WORD)wParam);
1626 
1627  case WM_CREATE:
1628  return DATETIME_Create (hwnd, (LPCREATESTRUCTW)lParam);
1629 
1630  case WM_DESTROY:
1631  return DATETIME_Destroy (infoPtr);
1632 
1633  case WM_COMMAND:
1634  return DATETIME_Command (infoPtr, wParam, lParam);
1635 
1636  case WM_STYLECHANGING:
1637  return DATETIME_StyleChanging(infoPtr, wParam, (LPSTYLESTRUCT)lParam);
1638 
1639  case WM_STYLECHANGED:
1640  return DATETIME_StyleChanged(infoPtr, wParam, (LPSTYLESTRUCT)lParam);
1641 
1642  case WM_SETFONT:
1643  return DATETIME_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
1644 
1645  case WM_GETFONT:
1646  return (LRESULT) infoPtr->hFont;
1647 
1648  case WM_GETTEXT:
1649  return (LRESULT) DATETIME_GetText(infoPtr, wParam, (LPWSTR)lParam);
1650 
1651  case WM_SETTEXT:
1652  return CB_ERR;
1653 
1654  default:
1655  if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg))
1656  ERR("unknown msg %04x wp=%08lx lp=%08lx\n",
1657  uMsg, wParam, lParam);
1658  return DefWindowProcW (hwnd, uMsg, wParam, lParam);
1659  }
1660 }
1661 
1662 
1663 void
1665 {
1666  WNDCLASSW wndClass;
1667 
1668  ZeroMemory (&wndClass, sizeof(WNDCLASSW));
1669  wndClass.style = CS_GLOBALCLASS;
1670  wndClass.lpfnWndProc = DATETIME_WindowProc;
1671  wndClass.cbClsExtra = 0;
1672  wndClass.cbWndExtra = sizeof(DATETIME_INFO *);
1673  wndClass.hCursor = LoadCursorW (0, (LPCWSTR)IDC_ARROW);
1674  wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
1676 
1677  RegisterClassW (&wndClass);
1678 }
1679 
1680 
1681 void
1683 {
1685 }
#define VK_SUBTRACT
Definition: winuser.h:2196
HGDIOBJ WINAPI GetStockObject(_In_ int)
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
#define DTM_GETRANGE
Definition: commctrl.h:4300
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
#define WS_DISABLED
Definition: pedump.c:621
#define HDC
Definition: msvc.h:22
BOOL dateValid
Definition: datetime.c:56
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define NM_KILLFOCUS
Definition: commctrl.h:136
#define DTM_SETRANGE
Definition: commctrl.h:4302
#define MCN_SELECT
Definition: commctrl.h:4272
#define max(a, b)
Definition: svc.c:63
void DATETIME_Unregister(void)
Definition: datetime.c:1682
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
unsigned short WORD
Definition: ntddk_ex.h:93
int * fieldspec
Definition: datetime.c:71
#define TRUE
Definition: types.h:120
#define DLGC_WANTCHARS
Definition: winuser.h:2562
#define FULLMONTH
Definition: datetime.c:104
static LRESULT DATETIME_StyleChanging(DATETIME_INFO *infoPtr, WPARAM wStyleType, STYLESTRUCT *lpss)
Definition: datetime.c:1403
#define DTHT_DATEFIELD
Definition: datetime.c:117
static BOOL DATETIME_SetFormatW(DATETIME_INFO *infoPtr, LPCWSTR format)
Definition: datetime.c:315
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define LOCALE_SABBREVMONTHNAME1
Definition: winnls.h:104
long y
Definition: polytest.cpp:48
#define DTN_DROPDOWN
Definition: commctrl.h:4418
UINT style
Definition: winuser.h:3119
#define WM_GETDLGCODE
Definition: winuser.h:1661
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
#define WM_CHAR
Definition: winuser.h:1683
#define WM_LBUTTONDOWN
Definition: winuser.h:1742
static unsigned int bufptr
Definition: tncon.cpp:77
#define INT_MAX
Definition: limits.h:40
BOOL WINAPI OffsetRect(_Inout_ LPRECT, _In_ int, _In_ int)
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
long x
Definition: polytest.cpp:48
USHORT wMonth
Definition: rtltypes.h:1568
#define MCM_GETMINREQRECT
Definition: commctrl.h:4167
#define TWODIGITYEAR
Definition: datetime.c:110
#define pt(x, y)
Definition: drawing.c:79
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define SW_HIDE
Definition: winuser.h:762
#define TWODIGITMONTH
Definition: datetime.c:102
static LRESULT DATETIME_Button_Command(DATETIME_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Definition: datetime.c:1050
#define CP_ACP
Definition: compat.h:99
#define DTM_SETFORMATW
Definition: commctrl.h:4305
#define TWODIGITDAY
Definition: datetime.c:92
#define LOCALE_SABBREVDAYNAME1
Definition: winnls.h:84
#define LOCALE_USER_DEFAULT
USHORT wDayOfWeek
Definition: rtltypes.h:1569
RECT calbutton
Definition: datetime.c:61
#define WM_GETTEXT
Definition: winuser.h:1590
#define WARN(fmt,...)
Definition: debug.h:111
#define THREECHARDAY
Definition: datetime.c:93
static LRESULT DATETIME_NCCreate(HWND hwnd, const CREATESTRUCTW *lpcs)
Definition: datetime.c:1293
#define MCM_GETRANGE
Definition: commctrl.h:4229
static LRESULT DATETIME_Create(HWND hwnd, const CREATESTRUCTW *lpcs)
Definition: datetime.c:1464
static LRESULT DATETIME_KeyDown(DATETIME_INFO *infoPtr, DWORD vkCode)
Definition: datetime.c:1141
#define DTHT_NONE
Definition: datetime.c:119
static BOOL DATETIME_SendDateTimeChangeNotify(const DATETIME_INFO *infoPtr)
Definition: datetime.c:1334
static LRESULT DATETIME_LButtonUp(DATETIME_INFO *infoPtr)
Definition: datetime.c:1019
#define DT_STRING
Definition: datetime.c:115
#define FULLDAY
Definition: datetime.c:94
#define DFCS_INACTIVE
Definition: winuser.h:502
UINT uMsg
Definition: precomp.h:53
#define FORMATCALLMASK
Definition: datetime.c:114
LONG top
Definition: windef.h:320
#define VK_ADD
Definition: winuser.h:2194
HANDLE HWND
Definition: compat.h:13
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define MONTHCAL_CLASSW
Definition: commctrl.h:4142
#define VK_LEFT
Definition: winuser.h:2168
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
#define UD_MINVAL
Definition: commctrl.h:2099
#define ZeroMemory
Definition: winbase.h:1621
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
#define TWOLETTERAMPM
Definition: datetime.c:108
#define GWL_EXSTYLE
Definition: winuser.h:840
GLuint buffer
Definition: glext.h:5915
int cbClsExtra
Definition: winuser.h:3121
HWND WINAPI SetFocus(_In_opt_ HWND)
HWND hwndNotify
Definition: datetime.c:52
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static INT DATETIME_GetText(const DATETIME_INFO *infoPtr, INT count, LPWSTR dst)
Definition: datetime.c:1520
BOOL WINAPI DrawFrameControl(_In_ HDC, _Inout_ LPRECT, _In_ UINT, _In_ UINT)
static BOOL DATETIME_SetFormatA(DATETIME_INFO *infoPtr, LPCSTR lpszFormat)
Definition: datetime.c:340
#define VK_DOWN
Definition: winuser.h:2171
#define WS_CHILD
Definition: pedump.c:617
#define GetWindowLongPtrW
Definition: winuser.h:4677
static LRESULT DATETIME_SetFont(DATETIME_INFO *infoPtr, HFONT font, BOOL repaint)
Definition: datetime.c:1455
LONG left
Definition: windef.h:319
#define SWP_NOZORDER
Definition: winuser.h:1222
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
static void DATETIME_IncreaseField(DATETIME_INFO *infoPtr, int number, int delta)
Definition: datetime.c:495
LONG right
Definition: windef.h:321
HFONT hFont
Definition: datetime.c:67
#define MCM_SETRANGE
Definition: commctrl.h:4231
BOOL bCalDepressed
Definition: datetime.c:62
HWND hMonthCal
Definition: datetime.c:51
#define lstrlenW
Definition: compat.h:407
#define WM_NCCREATE
Definition: winuser.h:1655
BOOL WINAPI DestroyWindow(_In_ HWND)
#define COLOR_WINDOW
Definition: winuser.h:898
int32_t INT
Definition: typedefs.h:56
int selection
Definition: ctm.c:90
DWORD DWORD
Definition: winlogon.h:75
int MONTHCAL_CalculateDayOfWeek(SYSTEMTIME *date, BOOL inplace)
Definition: monthcal.c:464
#define WM_ENABLE
Definition: winuser.h:1587
#define WM_PRINTCLIENT
Definition: richedit.h:70
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:656
UINT_PTR WPARAM
Definition: windef.h:230
RECT rcClient
Definition: datetime.c:58
#define DTM_GETMCFONT
Definition: commctrl.h:4319
#define DTM_SETMCFONT
Definition: commctrl.h:4317
UINT code
Definition: winuser.h:3102
INT WINAPI GetLocaleInfoW(LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len)
Definition: lang.c:807
COLORREF clrWindowText
Definition: comctl32.h:71
#define LOCALE_SDAYNAME1
Definition: winnls.h:77
#define ONEDIGITMONTH
Definition: datetime.c:101
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
#define DFCS_PUSHED
Definition: winuser.h:503
USHORT wYear
Definition: rtltypes.h:1567
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1032
WINE_DEFAULT_DEBUG_CHANNEL(datetime)
DWORD LCTYPE
Definition: winnls.h:505
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define VK_HOME
Definition: winuser.h:2167
#define MCM_GETCURSEL
Definition: commctrl.h:4151
#define LOCALE_SMONTHNAME1
Definition: winnls.h:91
COLORREF clrActiveCaption
Definition: comctl32.h:73
static LRESULT DATETIME_SetFocus(DATETIME_INFO *infoPtr, HWND lostFocus)
Definition: datetime.c:1305
#define VK_UP
Definition: winuser.h:2169
void DATETIME_Register(void)
Definition: datetime.c:1664
#define FULLYEAR
Definition: datetime.c:112
HWND hwndCheckbut
Definition: datetime.c:57
#define FALSE
Definition: types.h:117
#define ONEDIGIT24HOUR
Definition: datetime.c:97
long LONG
Definition: pedump.c:60
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
#define DTS_LONGDATEFORMAT
Definition: commctrl.h:4325
LONG_PTR LPARAM
Definition: windef.h:231
HWND WINAPI CreateUpDownControl(DWORD style, INT x, INT y, INT cx, INT cy, HWND parent, INT id, HINSTANCE inst, HWND buddy, INT maxVal, INT minVal, INT curVal)
Definition: commctrl.c:831
static size_t double number
Definition: printf.c:64
LONG WINAPI SetWindowLongW(_In_ HWND, _In_ int, _In_ LONG)
short SHORT
Definition: pedump.c:59
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
static void DATETIME_ApplySelectedField(DATETIME_INFO *infoPtr)
Definition: datetime.c:831
UINT_PTR idFrom
Definition: winuser.h:3101
#define debugstr_w
Definition: kernel32.h:32
static LRESULT DATETIME_Char(DATETIME_INFO *infoPtr, WPARAM vkCode)
Definition: datetime.c:1211
WNDPROC lpfnWndProc
Definition: winuser.h:3120
#define LOCALE_SLONGDATE
Definition: winnls.h:61
static void DATETIME_ReturnTxt(const DATETIME_INFO *infoPtr, int count, LPWSTR result, int resultSize)
Definition: datetime.c:358
#define FIXME(fmt,...)
Definition: debug.h:110
#define DTHT_NODATEMASK
Definition: datetime.c:123
static int DATETIME_GetPrevDateField(const DATETIME_INFO *infoPtr, int i)
Definition: datetime.c:821
#define TRANSPARENT
Definition: wingdi.h:948
LONG MONTHCAL_CompareSystemTime(const SYSTEMTIME *first, const SYSTEMTIME *second) DECLSPEC_HIDDEN
Definition: monthcal.c:299
HDC hdc
Definition: msvc.h:53
LONG WINAPI GetWindowLongW(_In_ HWND, _In_ int)
USHORT wMinute
Definition: rtltypes.h:1572
smooth NULL
Definition: ftsmooth.c:557
#define WM_GETFONT
Definition: winuser.h:1623
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:623
#define BS_AUTOCHECKBOX
Definition: pedump.c:654
#define SB_THUMBPOSITION
Definition: winuser.h:572
LONG cx
Definition: windef.h:347
#define WM_KEYDOWN
Definition: winuser.h:1681
LPCWSTR lpszClassName
Definition: winuser.h:3128
#define BM_GETCHECK
Definition: winuser.h:1869
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:276
#define DTM_GETMCCOLOR
Definition: commctrl.h:4313
const char * LPCSTR
Definition: xmlstorage.h:183
#define DT_VCENTER
Definition: winuser.h:543
#define SW_SHOW
Definition: winuser.h:769
#define WM_SETTEXT
Definition: winuser.h:1589
#define DFCS_SCROLLDOWN
Definition: winuser.h:490
static void DATETIME_UseFormat(DATETIME_INFO *infoPtr, LPCWSTR formattxt)
Definition: datetime.c:242
#define CB_ERR
Definition: winuser.h:2379
int haveFocus
Definition: datetime.c:70
#define WM_DESTROY
Definition: winuser.h:1581
GLuint GLfloat * val
Definition: glext.h:7180
#define MCM_SETCURSEL
Definition: commctrl.h:4153
#define MCM_SETCOLOR
Definition: commctrl.h:4169
static BOOL DATETIME_SendSimpleNotify(const DATETIME_INFO *infoPtr, UINT code)
Definition: datetime.c:1351
static void DATETIME_SetSelectedField(DATETIME_INFO *infoPtr, int select)
Definition: datetime.c:930
const char * wine_dbgstr_point(const POINT *guid)
#define BM_SETCHECK
Definition: winuser.h:1872
#define TRACE(s)
Definition: solgame.cpp:4
#define WM_KILLFOCUS
Definition: winuser.h:1586
unsigned int BOOL
Definition: ntddk_ex.h:94
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean flag
Definition: glfuncs.h:72
GLint GLint GLsizei width
Definition: gl.h:1546
int cbWndExtra
Definition: winuser.h:3122
#define WM_SIZE
Definition: winuser.h:1583
Definition: parser.c:43
#define TWODIGIT24HOUR
Definition: datetime.c:98
#define NM_SETFOCUS
Definition: commctrl.h:135
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static DWORD DATETIME_GetSystemTime(const DATETIME_INFO *infoPtr, SYSTEMTIME *systime)
Definition: datetime.c:135
UINT WPARAM wParam
Definition: precomp.h:53
#define SWP_NOACTIVATE
Definition: winuser.h:1217
static LRESULT DATETIME_Size(DATETIME_INFO *infoPtr, INT width, INT height)
Definition: datetime.c:1365
int MONTHCAL_MonthLength(int month, int year)
Definition: monthcal.c:211
int nCharsEntered
Definition: datetime.c:66
#define CS_GLOBALCLASS
Definition: winuser.h:647
BOOL WINAPI InvalidateRect(_In_opt_ HWND, _In_opt_ LPCRECT, _In_ BOOL)
PVOID Alloc(IN DWORD dwFlags, IN SIZE_T dwBytes)
Definition: main.c:63
static LRESULT DATETIME_Destroy(DATETIME_INFO *infoPtr)
Definition: datetime.c:1502
#define BN_CLICKED
Definition: winuser.h:1876
#define DTM_SETFORMATA
Definition: commctrl.h:4304
GLuint GLuint GLsizei count
Definition: gl.h:1545
HCURSOR WINAPI LoadCursorW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2076
#define DTS_RIGHTALIGN
Definition: commctrl.h:4329
int nrFieldsAllocated
Definition: datetime.c:68
static BOOL DATETIME_SetSystemTime(DATETIME_INFO *infoPtr, DWORD flag, const SYSTEMTIME *systime)
Definition: datetime.c:187
COMCTL32_SysColor comctl32_color
Definition: commctrl.c:70
WCHAR charsEntered[4]
Definition: datetime.c:65
#define DTM_GETSYSTEMTIME
Definition: commctrl.h:4296
#define DEFAULT_GUI_FONT
Definition: wingdi.h:907
USHORT wSecond
Definition: rtltypes.h:1573
#define WM_PAINT
Definition: winuser.h:1592
static LRESULT DATETIME_Notify(DATETIME_INFO *infoPtr, const NMHDR *lpnmh)
Definition: datetime.c:1115
USHORT wMilliseconds
Definition: rtltypes.h:1574
HANDLE HINSTANCE
Definition: typedefs.h:75
#define GDTR_MAX
Definition: commctrl.h:4422
#define DTM_GETMONTHCAL
Definition: commctrl.h:4315
#define UD_MAXVAL
Definition: commctrl.h:2098
#define DTM_SETSYSTEMTIME
Definition: commctrl.h:4298
static LRESULT DATETIME_LButtonDown(DATETIME_INFO *infoPtr, INT x, INT y)
Definition: datetime.c:939
static BOOL DATETIME_IsDateInValidRange(const DATETIME_INFO *infoPtr, const SYSTEMTIME *date)
Definition: datetime.c:160
HWND hUpdown
Definition: datetime.c:53
#define UDN_DELTAPOS
Definition: commctrl.h:2139
HWND WINAPI CreateWindowExW(_In_ DWORD dwExStyle, _In_opt_ LPCWSTR lpClassName, _In_opt_ LPCWSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
#define LOCALE_SSHORTDATE
Definition: winnls.h:60
#define GDTR_MIN
Definition: commctrl.h:4421
static int state
Definition: maze.c:121
static LRESULT WINAPI DATETIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: datetime.c:1540
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define GDT_NONE
Definition: commctrl.h:4426
GLenum GLsizei len
Definition: glext.h:6722
#define WM_APP
Definition: eventvwr.h:70
#define TWODIGIT12HOUR
Definition: datetime.c:96
#define WM_COMMAND
Definition: winuser.h:1706
#define NM_UPDOWN
Definition: commctrl.h:2130
HWND hwndFrom
Definition: winuser.h:3100
static const WCHAR allowedformatchars[]
Definition: datetime.c:127
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define BST_UNCHECKED
Definition: winuser.h:199
int code
Definition: i386-dis.c:3591
#define WINAPI
Definition: msvc.h:20
int * buflen
Definition: datetime.c:73
#define WM_USER
Definition: winuser.h:1846
#define ONEDIGIT12HOUR
Definition: datetime.c:95
GLenum GLint * range
Definition: glext.h:7539
#define VK_RIGHT
Definition: winuser.h:2170
#define TWODIGITMINUTE
Definition: datetime.c:100
#define INT_MIN
Definition: limits.h:39
int pendingUpdown
Definition: datetime.c:76
HCURSOR hCursor
Definition: winuser.h:3125
#define ERR(fmt,...)
Definition: debug.h:109
#define GWL_STYLE
Definition: winuser.h:841
#define ONEDIGITSECOND
Definition: datetime.c:105
RECT rcDraw
Definition: datetime.c:59
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:756
#define DTHT_MCPOPUP
Definition: datetime.c:121
USHORT wDay
Definition: rtltypes.h:1570
RECT checkbox
Definition: datetime.c:60
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define DT_SINGLELINE
Definition: winuser.h:540
COLORREF clrGrayText
Definition: comctl32.h:72
COLORREF clrBtnFace
Definition: comctl32.h:62
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
#define WS_BORDER
Definition: pedump.c:625
_In_ BOOL bEnable
Definition: winddi.h:3426
#define WS_EX_CLIENTEDGE
Definition: winuser.h:384
#define GDT_VALID
Definition: commctrl.h:4425
#define DATETIMEPICK_CLASSW
Definition: commctrl.h:4289
#define ONELETTERAMPM
Definition: datetime.c:107
static const int maxrepetition[]
Definition: datetime.c:128
__u16 date
Definition: mkdosfs.c:366
#define WC_BUTTONW
Definition: commctrl.h:4588
#define WM_CTLCOLOREDIT
Definition: winuser.h:1733
HBRUSH hbrBackground
Definition: winuser.h:3126
GLsizeiptr size
Definition: glext.h:5919
HWND hwndSelf
Definition: datetime.c:50
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define DTHT_GOTFOCUS
Definition: datetime.c:122
#define WM_LBUTTONUP
Definition: winuser.h:1743
USHORT wHour
Definition: rtltypes.h:1571
WINE_UNICODE_INLINE WCHAR * strcatW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:242
#define FORMATCALLBACK
Definition: datetime.c:113
#define DTS_SHOWNONE
Definition: commctrl.h:4323
DWORD styleNew
Definition: winuser.h:3614
UINT WPARAM LPARAM lParam
Definition: precomp.h:53
#define min(a, b)
Definition: monoChain.cc:55
#define WS_POPUP
Definition: pedump.c:616
unsigned int UINT
Definition: ndis.h:50
HBRUSH WINAPI CreateSolidBrush(_In_ COLORREF)
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLuint const GLubyte GLvoid const GLvoid * dst
Definition: s_context.h:57
#define DFC_SCROLL
Definition: winuser.h:475
#define MultiByteToWideChar
Definition: compat.h:100
#define WM_SETFONT
Definition: winuser.h:1622
#define BST_CHECKED
Definition: winuser.h:197
static LRESULT DATETIME_VScroll(DATETIME_INFO *infoPtr, WORD wScroll)
Definition: datetime.c:1252
int nrFields
Definition: datetime.c:69
DWORD styleOld
Definition: winuser.h:3613
static INT DATETIME_HitTest(const DATETIME_INFO *infoPtr, POINT pt)
Definition: datetime.c:803
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static LRESULT DATETIME_KillFocus(DATETIME_INFO *infoPtr, HWND lostFocus)
Definition: datetime.c:1276
BOOL WINAPI PtInRect(_In_ LPCRECT, _In_ POINT)
#define IDC_ARROW
Definition: winuser.h:682
#define DTN_CLOSEUP
Definition: commctrl.h:4419
_Out_opt_ int * cx
Definition: commctrl.h:570
#define GWLP_HINSTANCE
Definition: winuser.h:845
#define INVALIDFULLYEAR
Definition: datetime.c:111
static const SYSTEMTIME max_allowed_date
Definition: datetime.c:131
BOOL bDropdownEnabled
Definition: datetime.c:63
#define WM_CREATE
Definition: winuser.h:1580
static LRESULT DATETIME_Enable(DATETIME_INFO *infoPtr, BOOL bEnable)
Definition: datetime.c:1073
#define DTS_TIMEFORMAT
Definition: commctrl.h:4327
#define HIWORD(l)
Definition: typedefs.h:246
#define ONEDIGITYEAR
Definition: datetime.c:109
BOOL WINAPI IsWindowVisible(_In_ HWND)
SYSTEMTIME date
Definition: datetime.c:55
LONG bottom
Definition: windef.h:322
BOOL COMCTL32_IsReflectedMessage(UINT uMsg) DECLSPEC_HIDDEN
Definition: commctrl.c:1763
#define DT_CENTER
Definition: winuser.h:527
static LRESULT DATETIME_Paint(DATETIME_INFO *infoPtr, HDC hdc)
Definition: datetime.c:1031
#define MCM_GETCOLOR
Definition: commctrl.h:4171
static LRESULT DATETIME_StyleChanged(DATETIME_INFO *infoPtr, WPARAM wStyleType, const STYLESTRUCT *lpss)
Definition: datetime.c:1421
BOOL WINAPI SetWindowPos(_In_ HWND, _In_opt_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
#define SetWindowLongPtrW
Definition: winuser.h:5194
#define DTM_SETMCCOLOR
Definition: commctrl.h:4311
#define TWODIGITSECOND
Definition: datetime.c:106
RECT * fieldRect
Definition: datetime.c:72
#define WM_ERASEBKGND
Definition: winuser.h:1597
#define WM_SETFOCUS
Definition: winuser.h:1585
int month[12]
Definition: systime.c:13
struct DATETIME_INFO * LPDATETIME_INFO
_Check_return_ _CRTIMP double __cdecl floor(_In_ double x)
LONG_PTR LRESULT
Definition: windef.h:232
#define ss
Definition: i386-dis.c:432
static LRESULT DATETIME_EraseBackground(const DATETIME_INFO *infoPtr, HDC hdc)
Definition: datetime.c:1088
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
#define DTHT_CHECKBOX
Definition: datetime.c:120
COLORREF clrWindow
Definition: comctl32.h:70
#define WS_VISIBLE
Definition: pedump.c:620
#define THREECHARMONTH
Definition: datetime.c:103
DWORD COLORREF
Definition: windef.h:313
#define DTN_DATETIMECHANGE
Definition: commctrl.h:4331
INT INT y
Definition: msvc.h:62
GLuint64EXT * result
Definition: glext.h:11304
#define DTS_UPDOWN
Definition: commctrl.h:4322
WCHAR * LPWSTR
Definition: xmlstorage.h:184
POINT monthcal_pos
Definition: datetime.c:75
LONG cy
Definition: windef.h:348
#define LOCALE_STIMEFORMAT
Definition: winnls.h:62
static void DATETIME_ReturnFieldWidth(const DATETIME_INFO *infoPtr, HDC hdc, int count, SHORT *width)
Definition: datetime.c:598
#define ONEDIGITMINUTE
Definition: datetime.c:99
int k
Definition: mpi.c:3369
#define LOWORD(l)
Definition: pedump.c:82
#define VK_END
Definition: winuser.h:2166
#define GWLP_ID
Definition: winuser.h:849
#define DLGC_WANTARROWS
Definition: winuser.h:2554
WCHAR textbuf[256]
Definition: datetime.c:74
static const SYSTEMTIME min_allowed_date
Definition: datetime.c:132
static LRESULT DATETIME_Command(DATETIME_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
Definition: datetime.c:1063
BOOL WINAPI GetTextExtentPoint32W(_In_ HDC hdc, _In_reads_(c) LPCWSTR lpString, _In_ int c, _Out_ LPSIZE psizl)
#define WM_NOTIFY
Definition: richedit.h:61
static int wrap(int val, int delta, int minVal, int maxVal)
Definition: datetime.c:486
#define DT_END_FORMAT
Definition: datetime.c:90
#define LPARAM
Definition: msvc.h:38
#define WM_VSCROLL
Definition: winuser.h:1710
INT WINAPI DrawTextW(HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags)
Definition: defwnd.c:17
#define ONEDIGITDAY
Definition: datetime.c:91
DWORD dwStyle
Definition: datetime.c:54
INT x
Definition: msvc.h:62
static void DATETIME_Refresh(DATETIME_INFO *infoPtr, HDC hdc)
Definition: datetime.c:727