2016-04-14 20:35:50 -05:00
// 14 april 2016
# include "uipriv_windows.h"
struct fontDialog {
HWND hwnd ;
HWND familyCombobox ;
HWND styleCombobox ;
HWND sizeCombobox ;
// TODO desc;
fontCollection * fc ;
2016-04-14 21:25:32 -05:00
IDWriteFontFamily * * families ;
UINT32 nFamilies ;
2016-04-14 20:35:50 -05:00
} ;
2016-04-14 21:25:32 -05:00
static LRESULT cbAddString ( HWND cb , WCHAR * str )
{
LRESULT lr ;
lr = SendMessageW ( cb , CB_ADDSTRING , 0 , ( LPARAM ) str ) ;
if ( lr = = ( LRESULT ) CB_ERR | | lr = = ( LRESULT ) CB_ERRSPACE )
logLastError ( " error adding item to combobox in cbAddString() " ) ;
return lr ;
}
static LRESULT cbInsertStringAtTop ( HWND cb , WCHAR * str )
{
LRESULT lr ;
lr = SendMessageW ( cb , CB_INSERTSTRING , 0 , ( LPARAM ) str ) ;
if ( lr = = ( LRESULT ) CB_ERR | | lr = = ( LRESULT ) CB_ERRSPACE )
logLastError ( " error inserting item to combobox in cbInsertStringAtTop() " ) ;
return lr ;
}
2016-04-15 12:18:06 -05:00
static void wipeStylesBox ( struct fontDialog * f )
{
IDWriteFont * font ;
LRESULT i , n ;
n = SendMessageW ( f - > styleCombobox , CB_GETCOUNT , 0 , 0 ) ;
if ( n = = ( LRESULT ) CB_ERR )
logLastError ( " error getting combobox item count in wipeStylesBox() " ) ;
for ( i = 0 ; i < n ; i + + ) {
font = ( IDWriteFont * ) SendMessageW ( f - > styleCombobox , CB_GETITEMDATA , ( WPARAM ) i , 0 ) ;
if ( font = = ( IDWriteFont * ) CB_ERR )
logLastError ( " error getting font to release it in wipeStylesBox() " ) ;
font - > Release ( ) ;
}
SendMessageW ( f - > styleCombobox , CB_RESETCONTENT , 0 , 0 ) ;
}
static WCHAR * fontStyleName ( struct fontDialog * f , IDWriteFont * font )
{
IDWriteLocalizedStrings * str ;
BOOL exists ;
WCHAR * wstr ;
HRESULT hr ;
// first try this; if this is present, use it...
hr = font - > GetInformationalStrings ( DWRITE_INFORMATIONAL_STRING_PREFERRED_SUBFAMILY_NAMES , & str , & exists ) ;
if ( hr ! = S_OK )
logHRESULT ( " error getting preferred subfamily string in fontStyleName() " , hr ) ;
if ( exists )
goto good ;
// ...otherwise this font is good enough to be part of the main one on GDI as well, so try that name
hr = font - > GetInformationalStrings ( DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES , & str , & exists ) ;
if ( hr ! = S_OK )
logHRESULT ( " error getting Win32 subfamily string in fontStyleName() " , hr ) ;
// TODO what if !exists?
good :
wstr = fontCollectionCorrectString ( f - > fc , str ) ;
str - > Release ( ) ;
return wstr ;
}
static void familyChanged ( struct fontDialog * f )
{
LRESULT n ;
IDWriteFontList * specifics ;
IDWriteFont * specific ;
UINT32 i , ns ;
WCHAR * label ;
LRESULT pos ;
HRESULT hr ;
wipeStylesBox ( f ) ;
n = SendMessageW ( f - > familyCombobox , CB_GETCURSEL , 0 , 0 ) ;
if ( n = = ( LRESULT ) CB_ERR )
return ; // TODO restore previous selection
// TODO figure out what the correct sort order is
hr = f - > families [ n ] - > GetMatchingFonts (
DWRITE_FONT_WEIGHT_NORMAL ,
DWRITE_FONT_STRETCH_NORMAL ,
DWRITE_FONT_STYLE_NORMAL ,
& specifics ) ;
if ( hr ! = S_OK )
logHRESULT ( " error getting styles for font in familyChanged() " , hr ) ;
// TODO test mutliple streteches; all the fonts I have have only one stretch value
ns = specifics - > GetFontCount ( ) ;
for ( i = 0 ; i < ns ; i + + ) {
hr = specifics - > GetFont ( i , & specific ) ;
if ( hr ! = S_OK )
logHRESULT ( " error getting font for filling styles box in familyChanged() " , hr ) ;
label = fontStyleName ( f , specific ) ;
pos = cbAddString ( f - > styleCombobox , label ) ;
uiFree ( label ) ;
if ( SendMessageW ( f - > styleCombobox , CB_SETITEMDATA , ( WPARAM ) pos , ( LPARAM ) specific ) = = ( LRESULT ) CB_ERR )
logLastError ( " error setting font data in styles box in familyChanged() " ) ;
}
// TODO do we preserve style selection?
}
2016-04-14 20:35:50 -05:00
static struct fontDialog * beginFontDialog ( HWND hwnd , LPARAM lParam )
{
struct fontDialog * f ;
2016-04-14 21:25:32 -05:00
UINT32 i ;
WCHAR * wname ;
LRESULT ten ;
HRESULT hr ;
2016-04-14 20:35:50 -05:00
f = uiNew ( struct fontDialog ) ;
f - > hwnd = hwnd ;
f - > familyCombobox = GetDlgItem ( f - > hwnd , rcFontFamilyCombobox ) ;
if ( f - > familyCombobox = = NULL )
logLastError ( " error getting font family combobox handle in beginFontDialog() " ) ;
f - > styleCombobox = GetDlgItem ( f - > hwnd , rcFontStyleCombobox ) ;
if ( f - > styleCombobox = = NULL )
logLastError ( " error getting font style combobox handle in beginFontDialog() " ) ;
f - > sizeCombobox = GetDlgItem ( f - > hwnd , rcFontSizeCombobox ) ;
if ( f - > sizeCombobox = = NULL )
logLastError ( " error getting font size combobox handle in beginFontDialog() " ) ;
2016-04-14 21:25:32 -05:00
f - > fc = loadFontCollection ( ) ;
f - > nFamilies = f - > fc - > fonts - > GetFontFamilyCount ( ) ;
f - > families = new IDWriteFontFamily * [ f - > nFamilies ] ;
for ( i = 0 ; i < f - > nFamilies ; i + + ) {
hr = f - > fc - > fonts - > GetFontFamily ( i , & ( f - > families [ i ] ) ) ;
if ( hr ! = S_OK )
logHRESULT ( " error getting font family in beginFontDialog() " , hr ) ;
wname = fontCollectionFamilyName ( f - > fc , f - > families [ i ] ) ;
cbAddString ( f - > familyCombobox , wname ) ;
uiFree ( wname ) ;
}
// TODO all comboboxes should select on type; these already scroll on type but not select
// TODO behavior for the real thing:
// - if prior size is in list, select and scroll to it
// - if not, select nothing and don't scroll list at all (keep at top)
// we do 8 and 9 later
ten = cbAddString ( f - > sizeCombobox , L " 10 " ) ;
cbAddString ( f - > sizeCombobox , L " 11 " ) ;
cbAddString ( f - > sizeCombobox , L " 12 " ) ;
cbAddString ( f - > sizeCombobox , L " 14 " ) ;
cbAddString ( f - > sizeCombobox , L " 16 " ) ;
cbAddString ( f - > sizeCombobox , L " 18 " ) ;
cbAddString ( f - > sizeCombobox , L " 20 " ) ;
cbAddString ( f - > sizeCombobox , L " 22 " ) ;
cbAddString ( f - > sizeCombobox , L " 24 " ) ;
cbAddString ( f - > sizeCombobox , L " 26 " ) ;
cbAddString ( f - > sizeCombobox , L " 28 " ) ;
cbAddString ( f - > sizeCombobox , L " 36 " ) ;
cbAddString ( f - > sizeCombobox , L " 48 " ) ;
cbAddString ( f - > sizeCombobox , L " 72 " ) ;
if ( SendMessageW ( f - > sizeCombobox , CB_SETCURSEL , ( WPARAM ) ten , 0 ) ! = ten )
logLastError ( " error selecting 10 in the size combobox in beginFontDialog() " ) ;
// if we just use CB_ADDSTRING 8 and 9 will appear at the bottom of the list due to lexicographical sorting
// if we use CB_INSERTSTRING instead it won't
cbInsertStringAtTop ( f - > sizeCombobox , L " 9 " ) ;
cbInsertStringAtTop ( f - > sizeCombobox , L " 8 " ) ;
// 10 moved because of the above; figure out where it is now
// we selected it earlier; getting the selection is easiest
ten = SendMessageW ( f - > sizeCombobox , CB_GETCURSEL , 0 , 0 ) ;
// and finally put 10 at the top to imitate ChooseFont()
if ( SendMessageW ( f - > sizeCombobox , CB_SETTOPINDEX , ( WPARAM ) ten , 0 ) ! = 0 )
logLastError ( " error making 10 visible in the size combobox in beginFontDialog() " ) ;
2016-04-14 21:40:01 -05:00
// note: we can't add ES_NUMBER to the combobox entry (it seems to disable the entry instead?!), so we must do validation when the box is dmissed; TODO
2016-04-14 21:25:32 -05:00
2016-04-15 12:18:06 -05:00
// TODO actually select Arial
if ( SendMessageW ( f - > familyCombobox , CB_SETCURSEL , ( WPARAM ) 0 , 0 ) ! = 0 )
logLastError ( " error selecting Arial in the family combobox in beginFontDialog() " ) ;
familyChanged ( f ) ;
2016-04-14 20:35:50 -05:00
return f ;
}
static void endFontDialog ( struct fontDialog * f , INT_PTR code )
{
2016-04-14 21:25:32 -05:00
UINT32 i ;
2016-04-15 12:18:06 -05:00
wipeStylesBox ( f ) ;
2016-04-14 21:25:32 -05:00
for ( i = 0 ; i < f - > nFamilies ; i + + )
f - > families [ i ] - > Release ( ) ;
delete [ ] f - > families ;
fontCollectionFree ( f - > fc ) ;
2016-04-14 20:35:50 -05:00
if ( EndDialog ( f - > hwnd , code ) = = 0 )
logLastError ( " error ending font dialog in endFontDialog() " ) ;
uiFree ( f ) ;
}
static INT_PTR tryFinishDialog ( struct fontDialog * f , WPARAM wParam )
{
// cancelling
if ( LOWORD ( wParam ) ! = IDOK ) {
endFontDialog ( f , 1 ) ;
return TRUE ;
}
// TODO
endFontDialog ( f , 2 ) ;
return TRUE ;
}
static INT_PTR CALLBACK fontDialogDlgProc ( HWND hwnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
struct fontDialog * f ;
f = ( struct fontDialog * ) GetWindowLongPtrW ( hwnd , DWLP_USER ) ;
if ( f = = NULL ) {
if ( uMsg = = WM_INITDIALOG ) {
f = beginFontDialog ( hwnd , lParam ) ;
SetWindowLongPtrW ( hwnd , DWLP_USER , ( LONG_PTR ) f ) ;
return TRUE ;
}
return FALSE ;
}
switch ( uMsg ) {
case WM_COMMAND :
2016-04-15 12:18:06 -05:00
switch ( LOWORD ( wParam ) ) {
case IDOK :
case IDCANCEL :
if ( HIWORD ( wParam ) ! = BN_CLICKED )
return FALSE ;
return tryFinishDialog ( f , wParam ) ;
case rcFontFamilyCombobox :
if ( HIWORD ( wParam ) ! = CBN_SELCHANGE )
return FALSE ;
familyChanged ( f ) ;
return TRUE ;
}
return FALSE ;
2016-04-14 20:35:50 -05:00
}
return FALSE ;
}
void showFontDialog ( HWND parent )
{
switch ( DialogBoxParamW ( hInstance , MAKEINTRESOURCE ( rcFontDialog ) , parent , fontDialogDlgProc , ( LPARAM ) NULL ) ) {
case 1 :
// TODO cancel
break ;
case 2 :
// TODO OK
break ;
default :
logLastError ( " error running font dialog in showFontDialog() " ) ;
}
}