⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 varformat.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
      V_BOOL(&vBool) = VARIANT_TRUE;
    }
    else if (have_int == 1 && !exponent && rgbDig[0] == 0)
    {
      numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetZero(header));
      V_BOOL(&vBool) = VARIANT_FALSE;
    }
    else
    {
      numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetPositive(header));
      V_BOOL(&vBool) = VARIANT_TRUE;
    }

    TRACE("num header: flags = 0x%x, mult=%d, div=%d, whole=%d, fract=%d\n",
          numHeader->flags, numHeader->multiplier, numHeader->divisor,
          numHeader->whole, numHeader->fractional);

    need_int = numHeader->whole;
    need_frac = numHeader->fractional;

    if (numHeader->flags & FMT_FLAG_PERCENT &&
        !(have_int == 1 && !exponent && rgbDig[0] == 0))
      exponent += 2;

    if (numHeader->flags & FMT_FLAG_EXPONENT)
    {
      /* Exponent format: length of the integral number part is fixed and
         specified by the format. */
      pad = need_int - have_int;
      if (pad >= 0)
        exponent -= pad;
      else
      {
        have_int = need_int;
        have_frac -= pad;
        exponent -= pad;
        pad = 0;
      }
    }
    else
    {
      /* Convert the exponent */
      pad = max(exponent, -have_int);
      exponent -= pad;
      if (pad < 0)
      {
        have_int += pad;
        have_frac = -pad;
        pad = 0;
      }
    }

    /* Rounding the number */
    if (have_frac > need_frac)
    {
      prgbDig = &rgbDig[have_int + need_frac];
      have_frac = need_frac;
      if (*prgbDig >= 5)
      {
        while (prgbDig-- > rgbDig && *prgbDig == 9)
          *prgbDig = 0;
        if (prgbDig < rgbDig)
        {
          /* We reached the first digit and that was also a 9 */
          rgbDig[0] = 1;
          if (numHeader->flags & FMT_FLAG_EXPONENT)
            exponent++;
          else
          {
            rgbDig[have_int + need_frac] = 0;
            have_int++;
          }
        }
        else
          (*prgbDig)++;
      }
    }
    TRACE("have_int=%d,need_int=%d,have_frac=%d,need_frac=%d,pad=%d,exp=%d\n",
          have_int, need_int, have_frac, need_frac, pad, exponent);
  }

  pToken = (const BYTE*)numHeader + sizeof(FMT_NUMBER_HEADER);
  prgbDig = rgbDig;

  while (SUCCEEDED(hRes) && *pToken != FMT_GEN_END)
  {
    WCHAR defaultChar = '?';
    DWORD boolFlag, localeValue = 0;

    if (pToken - rgbTok > header->size)
    {
      ERR("Ran off the end of the format!\n");
      hRes = E_INVALIDARG;
      goto VARIANT_FormatNumber_Exit;
    }

    switch (*pToken)
    {
    case FMT_GEN_COPY:
      TRACE("copy %s\n", debugstr_wn(lpszFormat + pToken[1], pToken[2]));
      memcpy(pBuff, lpszFormat + pToken[1], pToken[2] * sizeof(WCHAR));
      pBuff += pToken[2];
      pToken += 2;
      break;

    case FMT_GEN_INLINE:
      pToken += 2;
      TRACE("copy %s\n", debugstr_a((LPCSTR)pToken));
      while (*pToken)
        *pBuff++ = *pToken++;
      break;

    case FMT_NUM_YES_NO:
      boolFlag = VAR_BOOLYESNO;
      goto VARIANT_FormatNumber_Bool;

    case FMT_NUM_ON_OFF:
      boolFlag = VAR_BOOLONOFF;
      goto VARIANT_FormatNumber_Bool;

    case FMT_NUM_TRUE_FALSE:
      boolFlag = VAR_LOCALBOOL;

VARIANT_FormatNumber_Bool:
      {
        BSTR boolStr = NULL;

        if (pToken[1] != FMT_GEN_END)
        {
          ERR("Boolean token not at end of format!\n");
          hRes = E_INVALIDARG;
          goto VARIANT_FormatNumber_Exit;
        }
        hRes = VarBstrFromBool(V_BOOL(&vBool), lcid, boolFlag, &boolStr);
        if (SUCCEEDED(hRes))
        {
          strcpyW(pBuff, boolStr);
          SysFreeString(boolStr);
          while (*pBuff)
            pBuff++;
        }
      }
      break;

    case FMT_NUM_DECIMAL:
      TRACE("write decimal separator\n");
      localeValue = LOCALE_SDECIMAL;
      defaultChar = '.';
      dwState |= NUM_WROTE_DEC;
      break;

    case FMT_NUM_CURRENCY:
      TRACE("write currency symbol\n");
      localeValue = LOCALE_SCURRENCY;
      defaultChar = '$';
      break;

    case FMT_NUM_EXP_POS_U:
    case FMT_NUM_EXP_POS_L:
    case FMT_NUM_EXP_NEG_U:
    case FMT_NUM_EXP_NEG_L:
      if (*pToken == FMT_NUM_EXP_POS_L || *pToken == FMT_NUM_EXP_NEG_L)
        *pBuff++ = 'e';
      else
        *pBuff++ = 'E';
      if (exponent < 0)
      {
        *pBuff++ = '-';
        sprintfW(pBuff, szPercentZeroStar_d, pToken[1], -exponent);
      }
      else
      {
        if (*pToken == FMT_NUM_EXP_POS_L || *pToken == FMT_NUM_EXP_POS_U)
          *pBuff++ = '+';
        sprintfW(pBuff, szPercentZeroStar_d, pToken[1], exponent);
      }
      while (*pBuff)
        pBuff++;
      pToken++;
      break;

    case FMT_NUM_COPY_ZERO:
      dwState |= NUM_WRITE_ON;
      /* Fall through */

    case FMT_NUM_COPY_SKIP:
      TRACE("write %d %sdigits or %s\n", pToken[1],
            dwState & NUM_WROTE_DEC ? "fractional " : "",
            *pToken == FMT_NUM_COPY_ZERO ? "0" : "skip");

      if (dwState & NUM_WROTE_DEC)
      {
        int count, i;

        if (!(numHeader->flags & FMT_FLAG_EXPONENT) && exponent < 0)
        {
          /* Pad with 0 before writing the fractional digits */
          pad = max(exponent, -pToken[1]);
          exponent -= pad;
          count = min(have_frac, pToken[1] + pad);
          for (i = 0; i > pad; i--)
            *pBuff++ = '0';
        }
        else
          count = min(have_frac, pToken[1]);

        pad += pToken[1] - count;
        have_frac -= count;
        while (count--)
          *pBuff++ = '0' + *prgbDig++;
        if (*pToken == FMT_NUM_COPY_ZERO)
        {
          for (; pad > 0; pad--)
            *pBuff++ = '0'; /* Write zeros for missing trailing digits */
        }
      }
      else
      {
        int count, count_max;

        need_int -= pToken[1];
        count_max = have_int + pad - need_int;
        if (count_max < 0)
            count_max = 0;
        if (dwState & NUM_WRITE_ON)
        {
          count = pToken[1] - count_max;
          TRACE("write %d leading zeros\n", count);
          while (count-- > 0)
            *pBuff++ = '0';
        }
        if (*pToken == FMT_NUM_COPY_ZERO || have_int > 1 || *prgbDig > 0)
        {
          dwState |= NUM_WRITE_ON;
          count = min(count_max, have_int);
          count_max -= count;
          have_int -= count;
          TRACE("write %d whole number digits\n", count);
          while (count--)
            *pBuff++ = '0' + *prgbDig++;
        }
        count = min(count_max, pad);
        count_max -= count;
        pad -= count;
        TRACE("write %d whole trailing 0's\n", count);
        while (count--)
          *pBuff++ = '0';
      }
      pToken++;
      break;

    default:
      ERR("Unknown token 0x%02x!\n", *pToken);
      hRes = E_INVALIDARG;
      goto VARIANT_FormatNumber_Exit;
    }
    if (localeValue)
    {
      if (GetLocaleInfoW(lcid, localeValue, pBuff, 
                         sizeof(buff)/sizeof(WCHAR)-(pBuff-buff)))
      {
        TRACE("added %s\n", debugstr_w(pBuff));
        while (*pBuff)
          pBuff++;
      }
      else
      {
        TRACE("added %d '%c'\n", defaultChar, defaultChar);
        *pBuff++ = defaultChar;
      }
    }
    pToken++;
  }

VARIANT_FormatNumber_Exit:
  VariantClear(&vString);
  *pBuff = '\0';
  TRACE("buff is %s\n", debugstr_w(buff));
  if (SUCCEEDED(hRes))
  {
    *pbstrOut = SysAllocString(buff);
    if (!*pbstrOut)
      hRes = E_OUTOFMEMORY;
  }
  return hRes;
}

/* Format a variant using a date format */
static HRESULT VARIANT_FormatDate(LPVARIANT pVarIn, LPOLESTR lpszFormat,
                                  LPBYTE rgbTok, ULONG dwFlags,
                                  BSTR *pbstrOut, LCID lcid)
{
  WCHAR buff[256], *pBuff = buff;
  VARIANT vDate;
  UDATE udate;
  FMT_HEADER *header = (FMT_HEADER*)rgbTok;
  FMT_DATE_HEADER *dateHeader;
  const BYTE* pToken = NULL;
  HRESULT hRes;

  TRACE("(%p->(%s%s),%s,%p,0x%08x,%p,0x%08x)\n", pVarIn, debugstr_VT(pVarIn),
        debugstr_VF(pVarIn), debugstr_w(lpszFormat), rgbTok, dwFlags, pbstrOut,
        lcid);

  V_VT(&vDate) = VT_EMPTY;

  if (V_TYPE(pVarIn) == VT_EMPTY || V_TYPE(pVarIn) == VT_NULL)
  {
    dateHeader = (FMT_DATE_HEADER*)(rgbTok + FmtGetNegative(header));
    V_DATE(&vDate) = 0;
  }
  else
  {
    USHORT usFlags = dwFlags & VARIANT_CALENDAR_HIJRI ? VAR_CALENDAR_HIJRI : 0;

    hRes = VariantChangeTypeEx(&vDate, pVarIn, LCID_US, usFlags, VT_DATE);
    if (FAILED(hRes))
      return hRes;
    dateHeader = (FMT_DATE_HEADER*)(rgbTok + FmtGetPositive(header));
  }

  hRes = VarUdateFromDate(V_DATE(&vDate), 0 /* FIXME: flags? */, &udate);
  if (FAILED(hRes))
    return hRes;
  pToken = (const BYTE*)dateHeader + sizeof(FMT_DATE_HEADER);

  while (*pToken != FMT_GEN_END)
  {
    DWORD dwVal = 0, localeValue = 0, dwFmt = 0;
    LPCWSTR szPrintFmt = NULL;
    WCHAR defaultChar = '?';

    if (pToken - rgbTok > header->size)
    {
      ERR("Ran off the end of the format!\n");
      hRes = E_INVALIDARG;
      goto VARIANT_FormatDate_Exit;
    }

    switch (*pToken)
    {
    case FMT_GEN_COPY:
      TRACE("copy %s\n", debugstr_wn(lpszFormat + pToken[1], pToken[2]));
      memcpy(pBuff, lpszFormat + pToken[1], pToken[2] * sizeof(WCHAR));
      pBuff += pToken[2];
      pToken += 2;
      break;

    case FMT_DATE_TIME_SEP:
      TRACE("time separator\n");
      localeValue = LOCALE_STIME;
      defaultChar = ':';
      break;

    case FMT_DATE_DATE_SEP:
      TRACE("date separator\n");
      localeValue = LOCALE_SDATE;
      defaultChar = '/';
      break;

    case FMT_DATE_GENERAL:
      {
        BSTR date = NULL;
        WCHAR *pDate;
        hRes = VarBstrFromDate(V_DATE(&vDate), lcid, 0, &date);
        if (FAILED(hRes))
          goto VARIANT_FormatDate_Exit;
	pDate = date;
        while (*pDate)
          *pBuff++ = *pDate++;
        SysFreeString(date);
      }
      break;

    case FMT_DATE_QUARTER:
      if (udate.st.wMonth <= 3)
        *pBuff++ = '1';
      else if (udate.st.wMonth <= 6)
        *pBuff++ = '2';
      else if (udate.st.wMonth <= 9)
        *pBuff++ = '3';
      else
        *pBuff++ = '4';
      break;

    case FMT_DATE_TIME_SYS:
      {
        /* FIXME: VARIANT_CALENDAR HIJRI should cause Hijri output */
        BSTR date = NULL;
        WCHAR *pDate;
        hRes = VarBstrFromDate(V_DATE(&vDate), lcid, VAR_TIMEVALUEONLY, &date);
        if (FAILED(hRes))
          goto VARIANT_FormatDate_Exit;
	pDate = date;
        while (*pDate)
          *pBuff++ = *pDate++;
        SysFreeString(date);
      }
      break;

    case FMT_DATE_DAY:
      szPrintFmt = szPercent_d;
      dwVal = udate.st.wDay;
      break;

    case FMT_DATE_DAY_0:
      szPrintFmt = szPercentZeroTwo_d;
      dwVal = udate.st.wDay;
      break;

    case FMT_DATE_DAY_SHORT:
      /* FIXME: VARIANT_CALENDAR HIJRI should cause Hijri output */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -