Nikolay Sivov : comctl32/monthcal: Fix title to use properly localized year/month format.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jun 18 07:55:03 CDT 2015


Module: wine
Branch: master
Commit: 035d0a159431d9d6b9affff46ce7ff84d1d0e990
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=035d0a159431d9d6b9affff46ce7ff84d1d0e990

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Jun 17 11:57:21 2015 +0300

comctl32/monthcal: Fix title to use properly localized year/month format.

---

 dlls/comctl32/monthcal.c | 76 +++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 63 insertions(+), 13 deletions(-)

diff --git a/dlls/comctl32/monthcal.c b/dlls/comctl32/monthcal.c
index a49fad7..5accbe6 100644
--- a/dlls/comctl32/monthcal.c
+++ b/dlls/comctl32/monthcal.c
@@ -866,10 +866,16 @@ static void MONTHCAL_PaintButton(MONTHCAL_INFO *infoPtr, HDC hdc, enum nav_direc
 /* paint a title with buttons and month/year string */
 static void MONTHCAL_PaintTitle(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)
 {
-  static const WCHAR fmt_monthW[] = { '%','s',' ','%','l','d',0 };
+  static const WCHAR mmmmW[] = {'M','M','M','M',0};
+  static const WCHAR mmmW[] = {'M','M','M',0};
+  static const WCHAR mmW[] = {'M','M',0};
+  static const WCHAR fmtyearW[] = {'%','l','d',0};
+  static const WCHAR fmtmmW[] = {'%','0','2','d',0};
+  static const WCHAR fmtmW[] = {'%','d',0};
   RECT *title = &infoPtr->calendars[calIdx].title;
   const SYSTEMTIME *st = &infoPtr->calendars[calIdx].month;
-  WCHAR buf_month[80], buf_fmt[80];
+  WCHAR monthW[80], strW[80], fmtW[80], yearW[6] /* valid year range is 1601-30827 */;
+  int yearoffset, monthoffset, shiftX;
   SIZE sz;
 
   /* fill header box */
@@ -880,21 +886,65 @@ static void MONTHCAL_PaintTitle(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRU
   SetTextColor(hdc, infoPtr->colors[MCSC_TITLETEXT]);
   SelectObject(hdc, infoPtr->hBoldFont);
 
-  GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME1 + st->wMonth - 1,
-                 buf_month, countof(buf_month));
+  /* draw formatted date string */
+  GetDateFormatW(LOCALE_USER_DEFAULT, DATE_YEARMONTH, st, NULL, strW, countof(strW));
+  DrawTextW(hdc, strW, strlenW(strW), title, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
+
+  GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SYEARMONTH, fmtW, countof(fmtW));
+  wsprintfW(yearW, fmtyearW, st->wYear);
+
+  /* month is trickier as it's possible to have different format pictures, we'll
+     test for M, MM, MMM, and MMMM */
+  if (strstrW(fmtW, mmmmW))
+    GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME1+st->wMonth-1, monthW, countof(monthW));
+  else if (strstrW(fmtW, mmmW))
+    GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVMONTHNAME1+st->wMonth-1, monthW, countof(monthW));
+  else if (strstrW(fmtW, mmW))
+    wsprintfW(monthW, fmtmmW, st->wMonth);
+  else
+    wsprintfW(monthW, fmtmW, st->wMonth);
 
-  wsprintfW(buf_fmt, fmt_monthW, buf_month, st->wYear);
-  DrawTextW(hdc, buf_fmt, strlenW(buf_fmt), title,
-                      DT_CENTER | DT_VCENTER | DT_SINGLELINE);
+  /* update hit boxes */
+  yearoffset = 0;
+  while (strW[yearoffset])
+  {
+    if (!strncmpW(&strW[yearoffset], yearW, strlenW(yearW)))
+        break;
+    yearoffset++;
+  }
 
-  /* update title rectangles with current month - used while testing hits */
-  GetTextExtentPoint32W(hdc, buf_fmt, strlenW(buf_fmt), &sz);
-  infoPtr->calendars[calIdx].titlemonth.left = title->right / 2 + title->left / 2 - sz.cx / 2;
-  infoPtr->calendars[calIdx].titleyear.right = title->right / 2 + title->left / 2 + sz.cx / 2;
+  monthoffset = 0;
+  while (strW[monthoffset])
+  {
+    if (!strncmpW(&strW[monthoffset], monthW, strlenW(monthW)))
+        break;
+    monthoffset++;
+  }
+
+  /* for left limits use offsets */
+  sz.cx = 0;
+  if (yearoffset)
+    GetTextExtentPoint32W(hdc, strW, yearoffset, &sz);
+  infoPtr->calendars[calIdx].titleyear.left = sz.cx;
+
+  sz.cx = 0;
+  if (monthoffset)
+    GetTextExtentPoint32W(hdc, strW, monthoffset, &sz);
+  infoPtr->calendars[calIdx].titlemonth.left = sz.cx;
 
-  GetTextExtentPoint32W(hdc, buf_month, strlenW(buf_month), &sz);
+  /* for right limits use actual string parts lengths */
+  GetTextExtentPoint32W(hdc, &strW[yearoffset], strlenW(yearW), &sz);
+  infoPtr->calendars[calIdx].titleyear.right = infoPtr->calendars[calIdx].titleyear.left + sz.cx;
+
+  GetTextExtentPoint32W(hdc, monthW, strlenW(monthW), &sz);
   infoPtr->calendars[calIdx].titlemonth.right = infoPtr->calendars[calIdx].titlemonth.left + sz.cx;
-  infoPtr->calendars[calIdx].titleyear.left   = infoPtr->calendars[calIdx].titlemonth.right;
+
+  /* Finally translate rectangles to match center aligned string,
+     hit rectangles are relative to title rectangle before translation. */
+  GetTextExtentPoint32W(hdc, strW, strlenW(strW), &sz);
+  shiftX = (title->right - title->left - sz.cx) / 2 + title->left;
+  OffsetRect(&infoPtr->calendars[calIdx].titleyear, shiftX, 0);
+  OffsetRect(&infoPtr->calendars[calIdx].titlemonth, shiftX, 0);
 }
 
 static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx)




More information about the wine-cvs mailing list