5#include "Stroika/Foundation/StroikaPreComp.h" 
    9DISABLE_COMPILER_MSC_WARNING_START (5054)
 
   11DISABLE_COMPILER_MSC_WARNING_END (5054)
 
   20#include "LedItApplication.h" 
   21#include "LedItResources.h" 
   23#include "FormatToolbar.h" 
   27#if qStroika_Foundation_Common_Platform_Windows 
   29using LocalComboBox = FormatToolbar::LocalComboBox;
 
   37BEGIN_MESSAGE_MAP (FormatToolbar, CToolBar)
 
   40ON_CBN_DROPDOWN (IDC_FONTSIZE, OnFontSizeDropDown)
 
   41ON_CBN_KILLFOCUS (IDC_FONTNAME, OnFontNameKillFocus)
 
   42ON_CBN_KILLFOCUS (IDC_FONTSIZE, OnFontSizeKillFocus)
 
   43ON_CBN_SETFOCUS (IDC_FONTNAME, OnComboSetFocus)
 
   44ON_CBN_SETFOCUS (IDC_FONTSIZE, OnComboSetFocus)
 
   45ON_CBN_CLOSEUP (IDC_FONTNAME, OnComboCloseUp)
 
   46ON_CBN_CLOSEUP (IDC_FONTSIZE, OnComboCloseUp)
 
   49static CSize GetBaseUnits (CFont* pFont)
 
   51    ASSERT (pFont != NULL);
 
   52    ASSERT (pFont->GetSafeHandle () != NULL);
 
   53    CWindowDC screenDC (NULL);
 
   54    pFont = screenDC.SelectObject (pFont);
 
   56    VERIFY (screenDC.GetTextMetrics (&tm));
 
   57    screenDC.SelectObject (pFont);
 
   59    return CSize (tm.tmAveCharWidth, tm.tmHeight);
 
   62FormatToolbar::FormatToolbar (FormatToolbarOwner& owner)
 
   66    fnt.Attach (GetStockObject (DEFAULT_GUI_FONT));
 
   67    m_szBaseUnits                = GetBaseUnits (&fnt);
 
   68    LocalComboBox::m_nFontHeight = m_szBaseUnits.cy;
 
   71void FormatToolbar::OnUpdateCmdUI (CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
 
   73    CToolBar::OnUpdateCmdUI (pTarget, bDisableIfNoHndler);
 
   75    if (!m_comboFontName.HasFocus () && !m_comboFontSize.HasFocus ())
 
   79void FormatToolbar::SyncToView ()
 
   81    IncrementalFontSpecification fsp = fOwner.GetCurFont ();
 
   82    if (fsp.GetFontNameSpecifier_Valid ()) {
 
   83        m_comboFontName.MatchFont (fsp.GetFontName ().c_str ());
 
   86        m_comboFontName.SetTheText (_T(
""));
 
   91    m_comboFontSize.SetTwipSize (fsp.GetPointSize_Valid () ? fsp.GetPointSize () * 20 : -1);
 
   94void FormatToolbar::OnFontSizeDropDown ()
 
   97    m_comboFontName.GetTheText (str);
 
   99    int     nIndex = m_comboFontName.FindStringExact (-1, str);
 
  100    if (nIndex != CB_ERR) {
 
  101        m_comboFontName.GetLBText (nIndex, lpszName);
 
  104    int nSize = m_comboFontSize.GetTwipSize ();
 
  107        AfxMessageBox(IDS_INVALID_NUMBER, MB_OK | MB_ICONINFORMATION);
 
  109        nSize = m_comboFontSize.m_nTwipsLast;
 
  111    else if ((nSize >= 0 && nSize < 20) || nSize > 32760) {
 
  113        AfxMessageBox(IDS_INVALID_FONTSIZE, MB_OK | MB_ICONINFORMATION);
 
  115        nSize = m_comboFontSize.m_nTwipsLast;
 
  118    CWindowDC screenDC (NULL);
 
  119    m_comboFontSize.EnumFontSizes (screenDC, (lpszName.GetLength () == 0) ? NULL : LPCTSTR (lpszName));
 
  120    m_comboFontSize.SetTwipSize (nSize);
 
  123void FormatToolbar::OnComboCloseUp ()
 
  125    NotifyOwner (NM_RETURN);
 
  128void FormatToolbar::OnComboSetFocus ()
 
  130    NotifyOwner (NM_SETFOCUS);
 
  133void FormatToolbar::OnFontNameKillFocus ()
 
  137    NotifyOwner (NM_KILLFOCUS);
 
  143    m_comboFontName.GetTheText (str); 
 
  144    m_comboFontName.SetTheText (str); 
 
  145    m_comboFontName.GetTheText (str); 
 
  148    if (not str.IsEmpty ()) {
 
  149        IncrementalFontSpecification fsp;
 
  150        int                          nIndex = m_comboFontName.FindStringExact (-1, str);
 
  151        if (nIndex != CB_ERR) {
 
  153            m_comboFontName.GetLBText (nIndex, name);
 
  154            fsp.SetFontName ((LPCTSTR)name);
 
  159            fsp.SetFontName ((LPCTSTR)str);
 
  161        fOwner.SetCurFont (fsp);
 
  165void FormatToolbar::OnFontSizeKillFocus ()
 
  167    NotifyOwner (NM_KILLFOCUS);
 
  168    int nSize = m_comboFontSize.GetTwipSize ();
 
  171        AfxMessageBox(IDS_INVALID_NUMBER, MB_OK | MB_ICONINFORMATION);
 
  173        nSize = m_comboFontSize.m_nTwipsLast;
 
  175    else if ((nSize >= 0 && nSize < 20) || nSize > 32760) {
 
  177        AfxMessageBox(IDS_INVALID_FONTSIZE, MB_OK | MB_ICONINFORMATION);
 
  179        nSize = m_comboFontSize.m_nTwipsLast;
 
  181    else if (nSize > 0) {
 
  184        cf.dwMask = CFM_SIZE;
 
  188        IncrementalFontSpecification fsp;
 
  189        fsp.SetPointSize (
static_cast<IncrementalFontSpecification::FontSize
> (nSize / 20));
 
  190        fOwner.SetCurFont (fsp);
 
  194int FormatToolbar::OnCreate (LPCREATESTRUCT lpCreateStruct)
 
  196    if (CToolBar::OnCreate (lpCreateStruct) == -1)
 
  199    CRect rect (0, 0, (3 * LF_FACESIZE * m_szBaseUnits.cx) / 2, 200);
 
  200    if (!m_comboFontName.Create (WS_TABSTOP | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWN | CBS_SORT | CBS_AUTOHSCROLL | CBS_HASSTRINGS | CBS_OWNERDRAWFIXED,
 
  201                                 rect, 
this, IDC_FONTNAME)) {
 
  202        TRACE0 (
"Failed to create fontname combo-box\n");
 
  205    m_comboFontName.LimitText (LF_FACESIZE);
 
  207    rect.SetRect (0, 0, 10 * m_szBaseUnits.cx, 200);
 
  208    if (!m_comboFontSize.Create (WS_TABSTOP | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWN, rect, 
this, IDC_FONTSIZE)) {
 
  209        TRACE0 (
"Failed to create fontsize combo-box\n");
 
  213    m_comboFontSize.LimitText (4);
 
  214    m_comboFontName.EnumFontFamiliesEx ();
 
  216    static UINT BASED_CODE format[] = {
 
  221        ID_SEPARATOR, kFontStyleBoldCmd, kFontStyleItalicCmd, kFontStyleUnderlineCmd, ID_CHAR_COLOR,
 
  222        ID_SEPARATOR, kJustifyLeftCmd,   kJustifyCenterCmd,   kJustifyRightCmd,
 
  225    if (!LoadBitmap (IDB_FORMATBAR) || !SetButtons (format, 
sizeof (format) / 
sizeof (UINT))) {
 
  226        TRACE0 (
"Failed to create FormatBar\n");
 
  229    SetBarStyle (GetBarStyle () | CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC | CBRS_HIDE_INPLACE);
 
  230    SetSizes (CSize (23, 22), CSize (16, 16));
 
  232    (void)str.LoadString (IDS_TITLE_FORMATBAR);
 
  239void FormatToolbar::PositionCombos ()
 
  244    m_comboFontName.SetItemHeight (-1, m_comboFontSize.GetItemHeight (-1));
 
  246    m_comboFontName.GetWindowRect (&rect);
 
  247    int nHeight = rect.Height ();
 
  249    m_comboFontName.GetWindowRect (&rect);
 
  250    SetButtonInfo (0, IDC_FONTNAME, TBBS_SEPARATOR, rect.Width ());
 
  251    GetItemRect (0, &rect); 
 
  252    m_comboFontName.SetWindowPos (NULL, rect.left, ((rect.Height () - nHeight) / 2) + rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
 
  254    m_comboFontSize.GetWindowRect (&rect);
 
  255    SetButtonInfo (2, IDC_FONTSIZE, TBBS_SEPARATOR, rect.Width ());
 
  256    GetItemRect (2, &rect); 
 
  257    m_comboFontSize.SetWindowPos (NULL, rect.left, ((rect.Height () - nHeight) / 2) + rect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
 
  260void FormatToolbar::NotifyOwner (UINT nCode)
 
  263    nm.hwndFrom = m_hWnd;
 
  264    nm.idFrom   = GetDlgCtrlID ();
 
  266    GetOwner ()->SendMessage (WM_NOTIFY, nm.idFrom, (LPARAM)&nm);
 
  274using FontComboBox = FormatToolbar::FontComboBox;
 
  279BEGIN_MESSAGE_MAP (FontComboBox, LocalComboBox)
 
  282FontComboBox::FontComboBox ()
 
  284    VERIFY (m_bmFontType.LoadBitmap (IDB_FONTTYPE));
 
  287void FontComboBox::EnumFontFamiliesEx ()
 
  292    vector<SDKString> fonts = LedItApplication::Get ().GetUsableFontNames ();
 
  293    for (vector<SDKString>::const_iterator i = fonts.begin (); i != fonts.end (); ++i) {
 
  294        AddString ((*i).c_str ());
 
  299BOOL CALLBACK AFX_EXPORT FontComboBox::CheckIsTrueTypeEnumFamCallback (ENUMLOGFONTEX* , NEWTEXTMETRICEX* , 
int FontType, LPVOID pThis)
 
  301    bool* bs = (
bool*)pThis;
 
  302    if (FontType & TRUETYPE_FONTTYPE) {
 
  308void FontComboBox::DrawItem (LPDRAWITEMSTRUCT lpDIS)
 
  310    ASSERT (lpDIS->CtlType == ODT_COMBOBOX);
 
  311    int id = (int)(WORD)lpDIS->itemID;
 
  313    CDC*  pDC = CDC::FromHandle (lpDIS->hDC);
 
  314    CRect rc (lpDIS->rcItem);
 
  315    if (lpDIS->itemState & ODS_FOCUS)
 
  316        pDC->DrawFocusRect (rc);
 
  317    int nIndexDC = pDC->SaveDC ();
 
  320    if (lpDIS->itemState & ODS_SELECTED) {
 
  321        brushFill.CreateSolidBrush (::GetSysColor (COLOR_HIGHLIGHT));
 
  322        pDC->SetTextColor (::GetSysColor (COLOR_HIGHLIGHTTEXT));
 
  325        brushFill.CreateSolidBrush (pDC->GetBkColor ());
 
  326    pDC->SetBkMode (TRANSPARENT);
 
  327    pDC->FillRect (rc, &brushFill);
 
  330    GetLBText (
id, strText);
 
  332    bool isTrueType = 
false;
 
  335        Characters::CString::Copy (lf.lfFaceName, std::size (lf.lfFaceName), 
static_cast<const TCHAR*
> (strText));
 
  336        CWindowDC screenDC{
nullptr};
 
  337        HDC       hDC = screenDC.m_hDC;
 
  338        ASSERT (hDC != NULL);
 
  339        ::EnumFontFamiliesEx (hDC, &lf, (FONTENUMPROC)CheckIsTrueTypeEnumFamCallback, (LPARAM)&isTrueType, NULL);
 
  343        dc.CreateCompatibleDC (pDC);
 
  344        CBitmap* pBitmap = dc.SelectObject (&m_bmFontType);
 
  345        pDC->BitBlt (rc.left, rc.top, BMW, BMH, &dc, BMW, 0, SRCAND);
 
  346        dc.SelectObject (pBitmap);
 
  350    pDC->TextOut (rc.left, rc.top, strText, strText.GetLength ());
 
  352    pDC->RestoreDC (nIndexDC);
 
  355void FontComboBox::MeasureItem (LPMEASUREITEMSTRUCT lpMIS)
 
  357    ASSERT (lpMIS->CtlType == ODT_COMBOBOX);
 
  358    ASSERT (m_nFontHeight > 0);
 
  362    lpMIS->itemWidth  = rc.Width ();
 
  363    lpMIS->itemHeight = max (BMH, m_nFontHeight);
 
  366int FontComboBox::CompareItem (LPCOMPAREITEMSTRUCT lpCIS)
 
  368    ASSERT (lpCIS->CtlType == ODT_COMBOBOX);
 
  369    int     id1 = (int)(WORD)lpCIS->itemID1;
 
  370    int     id2 = (int)(WORD)lpCIS->itemID2;
 
  376    GetLBText (id1, str1);
 
  377    GetLBText (id2, str2);
 
  378    return str1.Collate (str2);
 
  382void FontComboBox::MatchFont (LPCTSTR lpszName)
 
  384    int nFirstIndex = FindString (-1, lpszName);
 
  385    if (nFirstIndex != CB_ERR) {
 
  386        int nIndex = nFirstIndex;
 
  389            GetLBText (nIndex, str);
 
  390            if (lstrcmp (lpszName, str) == 0) {
 
  392                if (GetCurSel () != nIndex)
 
  396            nIndex = FindString (nIndex, lpszName);
 
  397        } 
while (nIndex != nFirstIndex);
 
  401    SetTheText (lpszName, TRUE);
 
  409using SizeComboBox = FormatToolbar::SizeComboBox;
 
  411SizeComboBox::SizeComboBox ()
 
  416void SizeComboBox::EnumFontSizes (CDC& dc, LPCTSTR pFontName)
 
  419    if (pFontName == NULL)
 
  421    if (pFontName[0] == NULL)
 
  424    ASSERT (dc.m_hDC != NULL);
 
  425    m_nLogVert = dc.GetDeviceCaps (LOGPIXELSY);
 
  426    ::EnumFontFamilies (dc.m_hDC, pFontName, (FONTENUMPROC)EnumSizeCallBack, (LPARAM)
this);
 
  429void SizeComboBox::TwipsToPointString (LPTSTR lpszBuf, 
int nTwips)
 
  431    ASSERT (lpszBuf != NULL);
 
  435        nTwips = (nTwips + 5) / 10;
 
  436        DISABLE_COMPILER_MSC_WARNING_START (4996)
 
  437        if ((nTwips % 2) == 0)
 
  438            _stprintf (lpszBuf, _T("%ld"), nTwips / 2);
 
  440            _stprintf (lpszBuf, _T("%.1f"), (
float)nTwips / 2.F);
 
  441        DISABLE_COMPILER_MSC_WARNING_END (4996)
 
  445void SizeComboBox::SetTwipSize (
int nTwips)
 
  447    if (nTwips != GetTwipSize ()) {
 
  449        TwipsToPointString (buf, nTwips);
 
  450        SetTheText (buf, TRUE);
 
  452    m_nTwipsLast = nTwips;
 
  455int SizeComboBox::GetTwipSize ()
 
  463    LPCTSTR lpszText = str;
 
  465    while (*lpszText == 
' ' || *lpszText == 
'\t')
 
  468    if (lpszText[0] == NULL)
 
  471    double d = _tcstod (lpszText, (LPTSTR*)&lpszText);
 
  472    while (*lpszText == 
' ' || *lpszText == 
'\t')
 
  475    if (*lpszText != NULL)
 
  478    return (d < 0.) ? 0 : (int)(d * 20.);
 
  481BOOL CALLBACK AFX_EXPORT SizeComboBox::EnumSizeCallBack (LOGFONT FAR* , LPNEWTEXTMETRIC lpntm, 
int FontType, LPVOID lpv)
 
  483    static int nFontSizes[] = {8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72};
 
  485    SizeComboBox* pThis = (SizeComboBox*)lpv;
 
  486    ASSERT (pThis != NULL);
 
  488    if ((FontType & TRUETYPE_FONTTYPE) || !((FontType & TRUETYPE_FONTTYPE) || (FontType & RASTER_FONTTYPE))) { 
 
  490        if (pThis->GetCount () != 0)
 
  491            pThis->ResetContent ();
 
  493        for (
int i = 0; i < 16; ++i) {
 
  494            wsprintf (buf, _T(
"%d"), nFontSizes[i]);
 
  495            pThis->AddString (buf);
 
  500    pThis->InsertSize (MulDiv (lpntm->tmHeight - lpntm->tmInternalLeading, 1440, pThis->m_nLogVert));
 
  504void SizeComboBox::InsertSize (
int nSize)
 
  507    DWORD dwSize = (DWORD)nSize;
 
  509    TwipsToPointString (buf, nSize);
 
  510    if (FindStringExact (-1, buf) == CB_ERR) {
 
  514        while ((dw = 
static_cast<DWORD
> (GetItemData (nPos))) != CB_ERR) {
 
  521        nIndex = InsertString (nIndex, buf);
 
  522        ASSERT (nIndex != CB_ERR);
 
  523        if (nIndex != CB_ERR)
 
  524            SetItemData (nIndex, dwSize);
 
  533using LocalComboBox = FormatToolbar::LocalComboBox;
 
  535int LocalComboBox::m_nFontHeight = 0;
 
  537BEGIN_MESSAGE_MAP (LocalComboBox, CComboBox)
 
  541void LocalComboBox::GetTheText (CString& str)
 
  543    int nIndex = GetCurSel ();
 
  544    if (nIndex == CB_ERR)
 
  547        GetLBText (nIndex, str);
 
  550void LocalComboBox::SetTheText (LPCTSTR lpszText, BOOL bMatchExact)
 
  552    int idx = (bMatchExact) ? FindStringExact (-1, lpszText) : FindString (-1, lpszText);
 
  553    SetCurSel ((idx == CB_ERR) ? -1 : idx);
 
  555        SetWindowText (lpszText);
 
  558BOOL LocalComboBox::LimitText (
int nMaxChars)
 
  560    BOOL b = CComboBox::LimitText (nMaxChars);
 
  562        m_nLimitText = nMaxChars;
 
  566int LocalComboBox::OnCreate (LPCREATESTRUCT lpCreateStruct)
 
  568    if (CComboBox::OnCreate (lpCreateStruct) == -1)
 
  570    SendMessage (WM_SETFONT, (WPARAM)GetStockObject (DEFAULT_GUI_FONT));
 
  574BOOL LocalComboBox::PreTranslateMessage (MSG* pMsg)
 
  576    if (pMsg->message == WM_KEYDOWN) {
 
  577        FormatToolbar* pBar = (FormatToolbar*)GetParent ();
 
  578        switch (pMsg->wParam) {
 
  581                pBar->NotifyOwner (NM_RETURN);
 
  584                pBar->NotifyOwner (NM_RETURN);
 
  587                pBar->GetNextDlgTabItem (
this)->SetFocus ();
 
  591                if ((GetKeyState (VK_MENU) >= 0) && (GetKeyState (VK_CONTROL) >= 0) && !GetDroppedState ()) {
 
  597    return CComboBox::PreTranslateMessage (pMsg);