int FontListCreate()

in src/propsheet/fontdlg.cpp [688:893]


int FontListCreate(
    __in HWND hDlg,
    __in_ecount_opt(LF_FACESIZE) LPWSTR pwszTTFace,
    __in BOOL bNewFaceList)
{
    LONG lListIndex;
    ULONG i;
    HWND hWndShow; // List or Combo box
    HWND hWndHide; // Combo or List box
    HWND hWndFaceCombo;
    BOOL bLB;
    UINT CodePage = gpStateInfo->CodePage;
    BOOL fFindTTFont = FALSE;
    LPWSTR pwszAltTTFace;
    LONG_PTR dwExStyle;

    FAIL_FAST_IF(!(OEMCP != 0)); // must be initialized

    bLB = ((pwszTTFace == nullptr) || (pwszTTFace[0] == TEXT('\0')));
    if (bLB)
    {
        pwszAltTTFace = nullptr;
    }
    else
    {
        if (ShouldAllowAllMonoTTFonts() || IsAvailableTTFont(pwszTTFace))
        {
            pwszAltTTFace = GetAltFaceName(pwszTTFace);
        }
        else
        {
            pwszAltTTFace = pwszTTFace;
        }
    }

    DBGFONTS(("FontListCreate %p, %s, %s new FaceList\n", hDlg, bLB ? "Raster" : "TrueType", bNewFaceList ? "Make" : "No"));

    /*
     * This only enumerates face names and font sizes if necessary.
     */
    if (!NT_SUCCESS(EnumerateFonts(bLB ? EF_OEMFONT : EF_TTFONT)))
    {
        return LB_ERR;
    }

    /* init the TTFaceNames */

    DBGFONTS(("  Create %s fonts\n", bLB ? "Raster" : "TrueType"));

    if (bNewFaceList)
    {
        PFACENODE panFace;
        hWndFaceCombo = GetDlgItem(hDlg, IDD_FACENAME);

        // empty faces list
        SendMessage(hWndFaceCombo, LB_RESETCONTENT, 0, 0);

        // before doing anything else, add raster fonts to the list. Note that the item data being set here indicates
        // that it's a raster font. the actual font indices are stored as item data on the pixels list.
        lListIndex = (LONG)SendMessage(hWndFaceCombo, LB_ADDSTRING, 0, (LPARAM)wszRasterFonts);
        SendMessage(hWndFaceCombo, LB_SETITEMDATA, lListIndex, TRUE);
        DBGFONTS(("Added \"%ls\", set Item Data %d = TRUE\n", wszRasterFonts, lListIndex));

        // now enumerate all of the new truetype font face names we've loaded that are appropriate for our codepage. add them to
        // the faces list. if we find an exact match for pwszTTFace or pwszAltTTFace, note that in fFindTTFont.
        for (panFace = gpFaceNames; panFace; panFace = panFace->pNext)
        {
            if ((panFace->dwFlag & (EF_TTFONT | EF_NEW)) != (EF_TTFONT | EF_NEW))
            {
                continue;
            }
            if (!g_fEastAsianSystem && (panFace->dwFlag & EF_DBCSFONT))
            {
                continue;
            }

            // NOTE: in v2 we don't depend on the registry list to determine if a TT font should be listed in the font
            // face dialog list -- this is handled in DoFontEnum by using the FontEnumForV2Console enumerator
            if (ShouldAllowAllMonoTTFonts() ||
                (g_fEastAsianSystem && IsAvailableTTFontCP(panFace->atch, CodePage)) ||
                (!g_fEastAsianSystem && IsAvailableTTFontCP(panFace->atch, 0)))
            {
                if (!bLB &&
                    (lstrcmp(pwszTTFace, panFace->atch) == 0 ||
                     lstrcmp(pwszAltTTFace, panFace->atch) == 0))
                {
                    fFindTTFont = TRUE;
                }

                lListIndex = (LONG)SendMessage(hWndFaceCombo, LB_ADDSTRING, 0, (LPARAM)panFace->atch);
                SendMessage(hWndFaceCombo, LB_SETITEMDATA, lListIndex, FALSE);
                DBGFONTS(("Added \"%ls\", set Item Data %d = FALSE\n",
                          panFace->atch,
                          lListIndex));
            }
        }

        // if we haven't found the specific TT font we're looking for, choose *any* TT font that's appropriate for our
        // codepage
        if (!bLB && !fFindTTFont)
        {
            for (panFace = gpFaceNames; panFace; panFace = panFace->pNext)
            {
                if ((panFace->dwFlag & (EF_TTFONT | EF_NEW)) != (EF_TTFONT | EF_NEW))
                {
                    continue;
                }

                if (!g_fEastAsianSystem && (panFace->dwFlag & EF_DBCSFONT))
                {
                    continue;
                }

                if ((g_fEastAsianSystem && IsAvailableTTFontCP(panFace->atch, CodePage)) ||
                    (!g_fEastAsianSystem && IsAvailableTTFontCP(panFace->atch, 0)))
                {
                    if (lstrcmp(pwszTTFace, panFace->atch) != 0)
                    {
                        // found a reasonably appropriate font that isn't the one being requested (we couldn't find that
                        // one). use this one instead.
                        StringCchCopy(pwszTTFace,
                                      LF_FACESIZE,
                                      panFace->atch);
                        break;
                    }
                }
            }
        }
    }

    // update the state of the bold checkbox. check the box if the currently selected TT font is bold. some TT fonts
    // aren't allowed to be bold depending on the charset. also, raster fonts aren't allowed to be bold.
    hWndShow = GetDlgItem(hDlg, IDD_BOLDFONT);

    /*
     * For JAPAN, We uses "MS Gothic" TT font.
     * So, Bold of this font is not 1:2 width between SBCS:DBCS.
     */
    if (g_fEastAsianSystem && IsDisableBoldTTFont(pwszTTFace))
    {
        EnableWindow(hWndShow, FALSE);
        gbBold = FALSE;
        CheckDlgButton(hDlg, IDD_BOLDFONT, FALSE);
    }
    else
    {
        CheckDlgButton(hDlg, IDD_BOLDFONT, (bLB || !gbBold) ? FALSE : TRUE);
        EnableWindow(hWndShow, bLB ? FALSE : TRUE);
    }

    // if the current font is raster, disable and hide the point size list.
    // if the current font is TT, disable and hide the pixel size list.
    hWndHide = GetDlgItem(hDlg, bLB ? IDD_POINTSLIST : IDD_PIXELSLIST);
    ShowWindow(hWndHide, SW_HIDE);
    EnableWindow(hWndHide, FALSE);

    // if the current font is raster, enable and show the pixel size list.
    // if the current font is TT, enable and show the point size list.
    hWndShow = GetDlgItem(hDlg, bLB ? IDD_PIXELSLIST : IDD_POINTSLIST);
    ShowWindow(hWndShow, SW_SHOW);
    EnableWindow(hWndShow, TRUE);

    // if we're building a new face list (basically any time we're not handling a selection change), empty the contents
    // of the pixel size list (raster) or point size list (TT) as appropriate.
    if (bNewFaceList)
    {
        lcbRESETCONTENT(hWndShow, bLB);
    }

    dwExStyle = GetWindowLongPtr(hWndShow, GWL_EXSTYLE);
    if ((dwExStyle & WS_EX_LAYOUTRTL) && !(dwExStyle & WS_EX_RTLREADING))
    {
        // if mirrored RTL Reading means LTR !!
        SetWindowLongPtr(hWndShow, GWL_EXSTYLE, dwExStyle | WS_EX_RTLREADING);
    }

    /* Initialize hWndShow list/combo box */

    const BOOL fIsBoldOnlyTTFont = (!bLB && IsBoldOnlyTTFont(pwszTTFace, pwszAltTTFace));

    AddFontSizesToList(pwszTTFace,
                       pwszAltTTFace,
                       dwExStyle,
                       g_fEastAsianSystem,
                       bLB,
                       hWndShow,
                       fIsBoldOnlyTTFont);

    if (fIsBoldOnlyTTFont)
    {
        // since this is a bold-only font, check and disable the bold checkbox
        EnableWindow(GetDlgItem(hDlg, IDD_BOLDFONT), FALSE);
        CheckDlgButton(hDlg, IDD_BOLDFONT, TRUE);
    }

    /*
     * Get the FontIndex from the currently selected item.
     * (i will be LB_ERR if no currently selected item).
     */
    lListIndex = lcbGETCURSEL(hWndShow, bLB);
    i = lcbGETITEMDATA(hWndShow, bLB, lListIndex);

    DBGFONTS(("FontListCreate returns 0x%x\n", i));
    FAIL_FAST_IF(!(i == LB_ERR || (ULONG)i < NumberOfFonts));
    return i;
}