get GetDateFormatW somewhat working...
Arthur L. Jones
aljones at lbl.gov
Thu Sep 19 16:25:48 CDT 2002
Changelog:
re-did OLE_GetFormatW so that dates are
formatted correctly for the XP app i am using
caveats: it just does what i needed, i attempted to
follow the docs on msdn but i have not tested anything
but a few basic dates. also, rather than figure out the
old OLE_GetFormatW i just reimplemented it, as
i figured it would take less time to do it this way, but i'm
sure it would be a better patch if i just fixed what didn't
work in OLE_GetFormatW.
notes: it seems like, if this ever worked correctly, that
OLE_GetFormatA could be implemented by just copying
the ascii buffer and sending it along to OLE_GetFormatW?
-------------- next part --------------
Index: ole/ole2nls.c
===================================================================
RCS file: /home/wine/wine/ole/ole2nls.c,v
retrieving revision 1.104
diff -r1.104 ole2nls.c
1573a1574,1583
> * OLE_GetRepW [INTERNAL]
> *
> * get count of repetitions of c...
> */
> static INT OLE_GetRepW(LPCWSTR s, WCHAR c)
> {
> int i = 0; while (s[i] == c) i++; return i;
> }
>
> /******************************************************************************
1574a1585,1633
> *
> *
> * dwFlags[in]:
> * LOCALE_NOUSEROVERRIDE : format the struct using system default date format
> * LOCALE_USE_CP_ACP :
> * DATE_SHORTDATE
> * DATE_LONGDATE
> * DATE_YEARMONTH
> * DATE_USE_ALT_CALENDAR
> * DATE_LTRREADING
> * DATE_RTLREADING
> *
> * xtime: pointer to SYSTEMTIME. if null, use current local system date
> *
> * format: if null, use date format of locale
> * d day as digits with no leading zero
> * dd day as digits with leading zero
> * ddd day as 3 char abbrev. uses LOCALE_SABBREVDAYNAME
> * dddd day as full name. uses LOCALE_SDAYNAME
> * M month as digits, no leading zero
> * MM month as digits, leading zero
> * MMM month as 3 char abbrev. uses LOCALE_SABBREVMONTHNAME
> * MMMM month as full name. uses LOCALE_SMONTHNAME
> * y year as last two digits, no leading zero
> * yy year as last two digits, leading zero
> * yyyy year as four digits
> * gg period, or era string. uses CAL_SERASTRING, not
> * used if date does not have an era or period string
> * h hours, no leading zero, 12hr clock
> * hh hours, leading zero, 12hr clock
> * H hours, no leading zero, 24hr clock
> * HH hours, leading zero, 24hr clock
> * m minutes, no leading zero
> * mm minutes, leading zero
> * s seconds, no leading zero
> * ss seconds, leading zero
> * t A or P
> * tt AM or PM
> *
> * output: zero terminated buffer
> *
> * outlen: specifies len of output. if
> * zero, the function returns the number of chars required
> * to format the date...
> *
> * FIXME:
> * verify xtime!
> * flags: DATE_USE_ALT_CALENDAR, DATE_LTREADING, DATE_RTREADING
> *
1577,1579c1636,1638
< const SYSTEMTIME* xtime,
< LPCWSTR format,
< LPWSTR output, INT outlen)
---
> const SYSTEMTIME* xtime,
> LPCWSTR format,
> LPWSTR output, INT outlen)
1581,1595c1640
< INT inpos, outpos;
< int count, type=0, inquote;
< int Overflow; /* loop check */
< char tmp[16];
< WCHAR buf[40];
< int buflen=0;
< WCHAR arg0[] = {0}, arg1[] = {'%','d',0};
< WCHAR arg2[] = {'%','0','2','d',0};
< WCHAR *argarr[3];
< int datevars=0, timevars=0;
<
< argarr[0] = arg0;
< argarr[1] = arg1;
< argarr[2] = arg2;
<
---
> INT inpos = 0, outpos = 0;
1602,1624c1647,1669
<
< if(outlen == 0) {
< FIXME("outlen = 0, returning 255\n");
< return 255;
< }
<
< /* initialize state variables */
< inpos = outpos = 0;
< count = 0;
< inquote = Overflow = 0;
< /* this is really just a sanity check */
< output[0] = buf[0] = 0;
<
< /* this loop is the core of the function */
< for (inpos = 0; /* we have several break points */ ; inpos++) {
< if (inquote) {
< if (format[inpos] == (WCHAR) '\'') {
< if (format[inpos+1] == '\'') {
< inpos++;
< output[outpos++] = '\'';
< } else {
< inquote = 0;
< continue;
---
>
> /* outlen must make sense
> */
> if (outlen<0) outlen = 0;
> if (outlen==0) output=NULL;
>
> while (format[inpos]) {
> WCHAR tmp[256];
> int tl = 0;
> char b[256];
>
> /* printf("format[%d]: %02x [%c] -> %d\n", inpos, format[inpos], format[inpos], outpos); */
>
> if (format[inpos] == (WCHAR) '\'') {
> inpos++;
> while (format[inpos]) {
> if (format[inpos]==(WCHAR)'\'') {
> /* ''' -> ' otherwise exit...
> */
> if (OLE_GetRepW(format+inpos, (WCHAR) '\'')>=3) {
> inpos+=2;
> }
> else break;
1626,1635c1671,1679
< } else if (format[inpos] == 0) {
< output[outpos++] = 0;
< if (outpos > outlen) Overflow = 1;
< break; /* normal exit (within a quote) */
< } else {
< output[outpos++] = format[inpos]; /* copy input */
< if (outpos > outlen) {
< Overflow = 1;
< output[outpos-1] = 0;
< break;
---
> if (output!=NULL) {
> if (outpos<outlen) {
> output[outpos] = format[inpos];
> }
> else {
> SetLastError(ERROR_INSUFFICIENT_BUFFER);
> if (outpos>0) output[outpos-1] = 0;
> return 0;
> }
1636a1681,1682
> outpos++;
> inpos++;
1638,1724c1684,1759
< } else if ( (count && (format[inpos] != type))
< || ( (count==4 && type =='y') ||
< (count==4 && type =='M') ||
< (count==4 && type =='d') ||
< (count==2 && type =='g') ||
< (count==2 && type =='h') ||
< (count==2 && type =='H') ||
< (count==2 && type =='m') ||
< (count==2 && type =='s') ||
< (count==2 && type =='t') ) ) {
< switch(type)
< {
< case 'd':
< if (count == 4) {
< GetLocaleInfoW(locale,
< LOCALE_SDAYNAME1 + (xtime->wDayOfWeek +6)%7,
< buf, sizeof(buf)/sizeof(WCHAR) );
< } else if (count == 3) {
< GetLocaleInfoW(locale,
< LOCALE_SABBREVDAYNAME1 +
< (xtime->wDayOfWeek +6)%7,
< buf, sizeof(buf)/sizeof(WCHAR) );
< } else {
< sprintf( tmp, "%.*d", count, xtime->wDay );
< MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
< }
< break;
<
< case 'M':
< if (count == 4) {
< GetLocaleInfoW(locale, LOCALE_SMONTHNAME1 +
< xtime->wMonth -1, buf,
< sizeof(buf)/sizeof(WCHAR) );
< } else if (count == 3) {
< GetLocaleInfoW(locale, LOCALE_SABBREVMONTHNAME1 +
< xtime->wMonth -1, buf,
< sizeof(buf)/sizeof(WCHAR) );
< } else {
< sprintf( tmp, "%.*d", count, xtime->wMonth );
< MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
< }
< break;
< case 'y':
< if (count == 4) {
< sprintf( tmp, "%d", xtime->wYear );
< } else if (count == 3) {
< strcpy( tmp, "yyy" );
< } else {
< sprintf( tmp, "%.*d", count, xtime->wYear % 100 );
< }
< MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
< break;
<
< case 'g':
< if (count == 2) {
< FIXME("LOCALE_ICALENDARTYPE unimplemented\n");
< strcpy( tmp, "AD" );
< } else {
< /* Win API sez we copy it verbatim */
< strcpy( tmp, "g" );
< }
< MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
< break;
<
< case 'h':
< /* hours 1:00-12:00 --- is this right? */
< sprintf( tmp, "%.*d", count, (xtime->wHour-1)%12 +1);
< MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
< break;
<
< case 'H':
< sprintf( tmp, "%.*d", count, xtime->wHour );
< MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
< break;
<
< case 'm':
< sprintf( tmp, "%.*d", count, xtime->wMinute );
< MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
< break;
<
< case 's':
< sprintf( tmp, "%.*d", count, xtime->wSecond );
< MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
< break;
<
< case 't':
< GetLocaleInfoW(locale, (xtime->wHour < 12) ?
---
> if (format[inpos]) inpos++;
> }
> else if (format[inpos] == (WCHAR) 'd') {
> const int cnt = OLE_GetRepW(format + inpos, (WCHAR) 'd');
> inpos += cnt;
> if (cnt==1 || cnt==2) {
> sprintf(b, (cnt==1) ? "%d" : "%02d", xtime->wDay);
> tl = MultiByteToWideChar(CP_ACP, 0, b, -1, tmp, sizeof(tmp)/sizeof(tmp[0]));
> }
> else {
> const int dow = (xtime->wDayOfWeek+6)%7;
> tl = GetLocaleInfoW(locale,
> ((cnt==3) ? LOCALE_SABBREVDAYNAME1 : LOCALE_SDAYNAME1) + dow,
> tmp, sizeof(tmp)/sizeof(tmp[0]));
> }
> }
> else if (format[inpos] == (WCHAR) 'M') {
> const int cnt = OLE_GetRepW(format + inpos, (WCHAR) 'M');
> const int mn = xtime->wMonth;
> inpos += cnt;
> if (cnt==1 || cnt==2) {
> sprintf(b, (cnt==1) ? "%d" : "%02d", mn);
> tl = MultiByteToWideChar(CP_ACP, 0, b, -1, tmp, sizeof(tmp)/sizeof(tmp[0]));
> }
> else {
> tl = GetLocaleInfoW(locale,
> ((cnt==3) ? LOCALE_SABBREVMONTHNAME1 : LOCALE_SMONTHNAME1) + mn,
> tmp, sizeof(tmp)/sizeof(tmp[0]));
> }
> }
> else if (format[inpos] == (WCHAR) 'y') {
> const int cnt = OLE_GetRepW(format + inpos, (WCHAR) 'y');
> const int yr = xtime->wYear;
> inpos += cnt;
> if (cnt==1 || cnt==2) {
> sprintf(b, (cnt==1) ? "%d" : "%02d", yr%100);
> }
> else sprintf(b, "%d", yr);
> tl = MultiByteToWideChar(CP_ACP, 0, b, -1, tmp, sizeof(tmp)/sizeof(tmp[0]));
> }
> else if (format[inpos] == (WCHAR) 'g') {
> const int cnt = OLE_GetRepW(format + inpos, (WCHAR) 'g');
> inpos += cnt;
> /* FIXME: which calendar id? we use 0...
> */
> tl = GetCalendarInfoW(locale, 0, CAL_SERASTRING,
> tmp, sizeof(tmp)/sizeof(tmp[0]), NULL);
> }
> else if (format[inpos] == (WCHAR) 'h') {
> const int cnt = OLE_GetRepW(format + inpos, (WCHAR) 'h');
> inpos += cnt;
> sprintf(b, (cnt==1) ? "%d" : "%02d", (xtime->wHour-1)%12+1);
> tl = MultiByteToWideChar(CP_ACP, 0, b, -1, tmp, sizeof(tmp)/sizeof(tmp[0]));
> }
> else if (format[inpos] == (WCHAR) 'H') {
> const int cnt = OLE_GetRepW(format + inpos, (WCHAR) 'H');
> inpos += cnt;
> sprintf(b, (cnt==1) ? "%d" : "%02d", xtime->wHour);
> tl = MultiByteToWideChar(CP_ACP, 0, b, -1, tmp, sizeof(tmp)/sizeof(tmp[0]));
> }
> else if (format[inpos] == (WCHAR) 'm') {
> const int cnt = OLE_GetRepW(format + inpos, (WCHAR) 'm');
> inpos += cnt;
> sprintf(b, (cnt==1) ? "%d" : "%02d", xtime->wMinute);
> tl = MultiByteToWideChar(CP_ACP, 0, b, -1, tmp, sizeof(tmp)/sizeof(tmp[0]));
> }
> else if (format[inpos] == (WCHAR) 's') {
> const int cnt = OLE_GetRepW(format + inpos, (WCHAR) 's');
> inpos += cnt;
> sprintf(b, (cnt==1) ? "%d" : "%02d", xtime->wSecond);
> tl = MultiByteToWideChar(CP_ACP, 0, b, -1, tmp, sizeof(tmp)/sizeof(tmp[0]));
> }
> else if (format[inpos] == (WCHAR) 't') {
> const int cnt = OLE_GetRepW(format + inpos, (WCHAR) 't');
> inpos += cnt;
> tl = GetLocaleInfoW(locale, (xtime->wHour < 12) ?
1726,1731c1761,1771
< buf, sizeof(buf) );
< if (count == 1) {
< buf[1] = 0;
< }
< break;
< }
---
> tmp, sizeof(tmp)/sizeof(tmp[0]));
> if (cnt==1 && tl>1) { tmp[1] = 0; tl = 2; }
> }
> /* default case, just copy output char...
> */
> else {
> tl = 2;
> tmp[0] = format[inpos];
> tmp[1] = 0;
> inpos++;
> }
1733,1745c1773,1787
< /* no matter what happened, we need to check this next
< character the next time we loop through */
< inpos--;
<
< /* cat buf onto the output */
< outlen = strlenW(buf);
< if (outpos + buflen < outlen) {
< strcpyW( output + outpos, buf );
< outpos += buflen;
< } else {
< lstrcpynW( output + outpos, buf, outlen - outpos );
< Overflow = 1;
< break; /* Abnormal exit */
---
> /* some characters buffered -- put them in output...
> */
> if (tl>0) {
> if (output!=NULL) {
> int j;
> for (j=0; j<tl-1; j++) {
> if (outpos+j<outlen) {
> output[outpos+j] = tmp[j];
> }
> else {
> if (outpos+j>0 && outlen>0) output[outpos+j-1] = 0;
> SetLastError(ERROR_INSUFFICIENT_BUFFER);
> return 0;
> }
> }
1746a1789,1791
> outpos+=tl-1;
> }
> }
1748,1754c1793,1794
< /* reset the variables we used this time */
< count = 0;
< type = '\0';
< } else if (format[inpos] == 0) {
< /* we can't check for this at the beginning, because that
< would keep us from printing a format spec that ended the
< string */
---
> if (output!=NULL) {
> if (outpos<outlen) {
1756,1778c1796,1799
< break; /* NORMAL EXIT */
< } else if (count) {
< /* how we keep track of the middle of a format spec */
< count++;
< continue;
< } else if ( (datevars && (format[inpos]=='d' ||
< format[inpos]=='M' ||
< format[inpos]=='y' ||
< format[inpos]=='g') ) ||
< (timevars && (format[inpos]=='H' ||
< format[inpos]=='h' ||
< format[inpos]=='m' ||
< format[inpos]=='s' ||
< format[inpos]=='t') ) ) {
< type = format[inpos];
< count = 1;
< continue;
< } else if (format[inpos] == '\'') {
< inquote = 1;
< continue;
< } else {
< /* unquoted literals */
< output[outpos++] = format[inpos];
---
> outpos++;
> }
> else {
> output[outpos-1]=0;
1782,1795c1803
< if (Overflow) {
< SetLastError(ERROR_INSUFFICIENT_BUFFER);
< WARN(" buffer overflow\n");
< };
<
< /* final string terminator and sanity check */
< outpos++;
< if (outpos > outlen-1) outpos = outlen-1;
< output[outpos] = '0';
<
< TRACE(" returning %s\n", debugstr_w(output));
<
< return (!Overflow) ? outlen : 0;
<
---
> return outpos;
1798d1805
<
1901c1908,1915
< unsigned short datearr[] = {'1','9','9','4','-','1','-','1',0};
---
> WCHAR format_buf[40];
> LPCWSTR thisformat;
> SYSTEMTIME t;
> LPSYSTEMTIME thistime;
> LCID thislocale;
> INT ret;
> FILETIME ft;
> BOOL res;
1903,1905c1917,1918
< FIXME("STUB (should call OLE_GetFormatW)\n");
< lstrcpynW(date, datearr, datelen);
< return ( datelen < 9) ? datelen : 9;
---
> TRACE("(0x%04lx,0x%08lx,%p,%p,%p,%d)\n",
> locale,flags,xtime,format,date,datelen);
1906a1920,1922
> if (!locale) {
> locale = LOCALE_SYSTEM_DEFAULT;
> };
1907a1924,1967
> if (locale == LOCALE_SYSTEM_DEFAULT) {
> thislocale = GetSystemDefaultLCID();
> } else if (locale == LOCALE_USER_DEFAULT) {
> thislocale = GetUserDefaultLCID();
> } else {
> thislocale = locale;
> };
>
>
> if (xtime == NULL) {
> GetSystemTime(&t);
> } else {
> /* Silently correct wDayOfWeek by transforming to FileTime and back again */
> res=SystemTimeToFileTime(xtime,&ft);
> /* Check year(?)/month and date for range and set ERROR_INVALID_PARAMETER on error */
> /*FIXME: SystemTimeToFileTime doesn't yet do that check */
> if(!res)
> {
> SetLastError(ERROR_INVALID_PARAMETER);
> return 0;
> }
> FileTimeToSystemTime(&ft,&t);
>
> };
> thistime = &t;
>
> if (format == NULL) {
> GetLocaleInfoW(thislocale, ((flags&DATE_LONGDATE)
> ? LOCALE_SLONGDATE
> : LOCALE_SSHORTDATE),
> format_buf, sizeof(format_buf));
> thisformat = format_buf;
> } else {
> thisformat = format;
> };
>
>
> ret = OLE_GetFormatW(thislocale, flags, 0, thistime, thisformat,
> date, datelen);
>
> TRACE(
> "GetDateFormatW() returning %d, with data=%p\n",
> ret, date);
> return ret;
More information about the wine-patches
mailing list