Implemented EnumCalendarInfo(A/W/ExA/ExW).
authorKen Belleau <jamez@ivic.qc.ca>
Tue, 14 Dec 2004 19:59:43 +0000 (19:59 +0000)
committerAlexandre Julliard <julliard@winehq.org>
Tue, 14 Dec 2004 19:59:43 +0000 (19:59 +0000)
dlls/kernel/kernel32.spec
dlls/kernel/lcformat.c

index 0462b77e701cd1bb756bcc6ced38d8bdeda7e57f..3640b4496dcbccf2c40fdedc52157088bb1bc57e 100644 (file)
 @ stdcall EndUpdateResourceW(long long)
 @ stdcall EnterCriticalSection(ptr) ntdll.RtlEnterCriticalSection
 @ stdcall EnumCalendarInfoA(ptr long long long)
-@ stub EnumCalendarInfoW
-@ stub EnumCalendarInfoExA
-@ stub EnumCalendarInfoExW
+@ stdcall EnumCalendarInfoW(ptr long long long)
+@ stdcall EnumCalendarInfoExA(ptr long long long)
+@ stdcall EnumCalendarInfoExW(ptr long long long)
 @ stdcall EnumDateFormatsA(ptr long long)
 @ stdcall EnumDateFormatsW(ptr long long)
 @ stub EnumDateFormatsExA
index 69f3d0120520f51e8fefb338526667e6508a868c..8376fcd2c51472b8b9140408591c80906fd8f6d0 100644 (file)
@@ -1934,12 +1934,189 @@ BOOL WINAPI EnumTimeFormatsW( TIMEFMT_ENUMPROCW lpTimeFmtEnumProc, LCID Locale,
   return FALSE;
 }
 
+/******************************************************************************
+ * NLS_EnumCalendarInfoAW <internal>
+ * Enumerates calendar information for a specified locale.
+ *
+ * PARAMS
+ *    calinfoproc [I] Pointer to the callback
+ *    locale      [I] The locale for which to retrieve calendar information.
+ *                    This parameter can be a locale identifier created by the
+ *                    MAKELCID macro, or one of the following values:
+ *                        LOCALE_SYSTEM_DEFAULT
+ *                            Use the default system locale.
+ *                        LOCALE_USER_DEFAULT
+ *                            Use the default user locale.
+ *    calendar    [I] The calendar for which information is requested, or
+ *                    ENUM_ALL_CALENDARS.
+ *    caltype     [I] The type of calendar information to be returned. Note
+ *                    that only one CALTYPE value can be specified per call
+ *                    of this function, except where noted.
+ *    unicode     [I] Specifies if the callback expects a unicode string.
+ *    ex          [I] Specifies if the callback needs the calendar identifier.
+ *
+ * RETURNS
+ *    Success: TRUE.
+ *    Failure: FALSE. Use GetLastError() to determine the cause.
+ *
+ * NOTES
+ *    When the ANSI version of this function is used with a Unicode-only LCID,
+ *    the call can succeed because the system uses the system code page.
+ *    However, characters that are undefined in the system code page appear
+ *    in the string as a question mark (?).
+ *
+ * TODO
+ *    The above note should be respected by GetCalendarInfoA.
+ */
+BOOL WINAPI NLS_EnumCalendarInfoAW(void *calinfoproc, LCID locale,
+                  CALID calendar, CALTYPE caltype, BOOL unicode, BOOL ex )
+{
+  WCHAR *buf, *opt = NULL, *iter = NULL;
+  BOOL ret = FALSE;
+  int bufSz = 200;             /* the size of the buffer */
+
+  if (calinfoproc == NULL)
+  {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+  }
+
+  buf = HeapAlloc(GetProcessHeap(), 0, bufSz);
+  if (buf == NULL)
+  {
+    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    return FALSE;
+  }
+
+  if (calendar == ENUM_ALL_CALENDARS)
+  {
+    int optSz = GetLocaleInfoW(locale, LOCALE_IOPTIONALCALENDAR, NULL, 0);
+    if (optSz > 1)
+    {
+      opt = HeapAlloc(GetProcessHeap(), 0, optSz * sizeof(WCHAR));
+      if (opt == NULL)
+      {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        goto NLS_EnumCalendarInfoAW_Cleanup;
+      }
+      if (GetLocaleInfoW(locale, LOCALE_IOPTIONALCALENDAR, opt, optSz))
+        iter = opt;
+    }
+    calendar = NLS_GetLocaleNumber(locale, LOCALE_ICALENDARTYPE);
+  }
+
+  while (TRUE)                 /* loop through calendars */
+  {
+    do                         /* loop until there's no error */
+    {
+      if (unicode)
+        ret = GetCalendarInfoW(locale, calendar, caltype, buf, bufSz / sizeof(WCHAR), NULL);
+      else ret = GetCalendarInfoA(locale, calendar, caltype, (CHAR*)buf, bufSz / sizeof(CHAR), NULL);
+
+      if (!ret)
+      {
+        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+        {                              /* so resize it */
+          int newSz;
+          if (unicode)
+            newSz = GetCalendarInfoW(locale, calendar, caltype, NULL, 0, NULL) * sizeof(WCHAR);
+          else newSz = GetCalendarInfoA(locale, calendar, caltype, NULL, 0, NULL) * sizeof(CHAR);
+          if (bufSz >= newSz)
+          {
+            ERR("Buffer resizing disorder: was %d, requested %d.\n", bufSz, newSz);
+            goto NLS_EnumCalendarInfoAW_Cleanup;
+          }
+          bufSz = newSz;
+          WARN("Buffer too small; resizing to %d bytes.\n", bufSz);
+          buf = HeapReAlloc(GetProcessHeap(), 0, buf, bufSz);
+          if (buf == NULL)
+            goto NLS_EnumCalendarInfoAW_Cleanup;
+        } else goto NLS_EnumCalendarInfoAW_Cleanup;
+      }
+    } while (!ret);
+
+    /* Here we are. We pass the buffer to the correct version of
+     * the callback. Because it's not the same number of params,
+     * we must check for Ex, but we don't care about Unicode
+     * because the buffer is already in the correct format.
+     */
+    if (ex) {
+      ret = ((CALINFO_ENUMPROCEXW)calinfoproc)(buf, calendar);
+    } else
+      ret = ((CALINFO_ENUMPROCW)calinfoproc)(buf);
+
+    if (!ret) {                        /* the callback told to stop */
+      ret = TRUE;
+      break;
+    }
+
+    if ((iter == NULL) || (*iter == 0))        /* no more calendars */
+      break;
+
+    calendar = 0;
+    while ((*iter >= '0') && (*iter <= '9'))
+      calendar = calendar * 10 + *iter++ - '0';
+
+    if (*iter++ != 0)
+    {
+      SetLastError(ERROR_BADDB);
+      ret = FALSE;
+      break;
+    }
+  }
+
+NLS_EnumCalendarInfoAW_Cleanup:
+  if (opt != NULL)
+    HeapFree(GetProcessHeap(), 0, opt);
+  if (buf != NULL)
+    HeapFree(GetProcessHeap(), 0, buf);
+  return ret;
+}
+
 /******************************************************************************
  *             EnumCalendarInfoA       [KERNEL32.@]
+ *
+ * See EnumCalendarInfoAW.
  */
 BOOL WINAPI EnumCalendarInfoA( CALINFO_ENUMPROCA calinfoproc,LCID locale,
                                CALID calendar,CALTYPE caltype )
 {
-    FIXME("(%p,0x%04lx,0x%08lx,0x%08lx),stub!\n",calinfoproc,locale,calendar,caltype);
-    return FALSE;
+  TRACE("(%p,0x%08lx,0x%08lx,0x%08lx)\n", calinfoproc, locale, calendar, caltype);
+  return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, FALSE, FALSE);
+}
+
+/******************************************************************************
+ *             EnumCalendarInfoW       [KERNEL32.@]
+ *
+ * See EnumCalendarInfoAW.
+ */
+BOOL WINAPI EnumCalendarInfoW( CALINFO_ENUMPROCW calinfoproc,LCID locale,
+                               CALID calendar,CALTYPE caltype )
+{
+  TRACE("(%p,0x%08lx,0x%08lx,0x%08lx)\n", calinfoproc, locale, calendar, caltype);
+  return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, TRUE, FALSE);
+}
+
+/******************************************************************************
+ *             EnumCalendarInfoExA     [KERNEL32.@]
+ *
+ * See EnumCalendarInfoAW.
+ */
+BOOL WINAPI EnumCalendarInfoExA( CALINFO_ENUMPROCEXA calinfoproc,LCID locale,
+                                 CALID calendar,CALTYPE caltype )
+{
+  TRACE("(%p,0x%08lx,0x%08lx,0x%08lx)\n", calinfoproc, locale, calendar, caltype);
+  return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, FALSE, TRUE);
+}
+
+/******************************************************************************
+ *             EnumCalendarInfoExW     [KERNEL32.@]
+ *
+ * See EnumCalendarInfoAW.
+ */
+BOOL WINAPI EnumCalendarInfoExW( CALINFO_ENUMPROCEXW calinfoproc,LCID locale,
+                                 CALID calendar,CALTYPE caltype )
+{
+  TRACE("(%p,0x%08lx,0x%08lx,0x%08lx)\n", calinfoproc, locale, calendar, caltype);
+  return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, TRUE, TRUE);
 }