From 0cb43dd17c2be7364dd57e7c4b91c571bd9fe5b5 Mon Sep 17 00:00:00 2001 From: thisismy-github <48284263+thisismy-github@users.noreply.github.com> Date: Wed, 11 Aug 2021 23:58:33 -0400 Subject: [PATCH 001/155] Added option to always single-click folders Opens pinned items on both sides of the start menu in just one click, while preserving hover functionality. Ignores the All Programs button for now as the All Programs folder is rarely accessed and this option can obstruct its use, especially for the inline menu style. Fixes #692. --- Src/StartMenu/StartMenuDLL/MenuContainer.cpp | 4 +++- Src/StartMenu/StartMenuDLL/MenuContainer.h | 1 + Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 1 + Src/StartMenu/StartMenuDLL/StartMenuDLL.rc | 6 ++++++ Src/StartMenu/StartMenuDLL/resource.h | 2 ++ 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp index 29413ddab..8fc20af43 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp @@ -315,6 +315,7 @@ bool CMenuContainer::s_bShowTopEmpty=false; bool CMenuContainer::s_bNoDragDrop=false; bool CMenuContainer::s_bNoContextMenu=false; bool CMenuContainer::s_bExpandLinks=false; +bool CMenuContainer::s_bSingleClickFolders=false; bool CMenuContainer::s_bLogicalSort=false; bool CMenuContainer::s_bExtensionSort=false; bool CMenuContainer::s_bAllPrograms=false; @@ -6823,7 +6824,7 @@ LRESULT CMenuContainer::OnLButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BO const MenuItem &item=m_Items[index]; POINT pt2=pt; ClientToScreen(&pt2); - if (!item.bFolder) + if (!item.bFolder || (s_bSingleClickFolders && item.id!=MENU_PROGRAMS)) // never open All Programs link with single click { if (item.jumpIndex>=0 && m_bHotArrow) { @@ -7672,6 +7673,7 @@ HWND CMenuContainer::ToggleStartMenu( int taskbarId, bool bKeyboard, bool bAllPr g_ItemManager.ResetTempIcons(); s_ScrollMenus=GetSettingInt(L"ScrollType"); s_bExpandLinks=GetSettingBool(L"ExpandFolderLinks"); + s_bSingleClickFolders=GetSettingBool(L"SingleClickFolders"); s_bLogicalSort=GetSettingBool(L"NumericSort"); s_MaxRecentDocuments=GetSettingInt(L"MaxRecentDocuments"); s_ShellFormat=RegisterClipboardFormat(CFSTR_SHELLIDLIST); diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.h b/Src/StartMenu/StartMenuDLL/MenuContainer.h index 696e8db48..ad34beb27 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.h +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.h @@ -876,6 +876,7 @@ class CMenuContainer: public IDropTarget, public IFrameworkInputPaneHandler, pub static bool s_bNoDragDrop; // disables drag/drop static bool s_bNoContextMenu; // disables the context menu static bool s_bExpandLinks; // expand links to folders + static bool s_bSingleClickFolders; // open links to folders with one click instead of two static bool s_bLogicalSort; // use StrCmpLogical instead of CompareString static bool s_bExtensionSort; // sort file names by extension static bool s_bAllPrograms; // this is the All Programs menu of the Windows start menu diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index 54007e93c..8a7b7b240 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -4313,6 +4313,7 @@ CSetting g_Settings[]={ {L"UserNameCommand",CSetting::TYPE_STRING,IDS_NAME_COMMAND,IDS_NAME_COMMAND_TIP,L"control nusrmgr.cpl"}, {L"SearchFilesCommand",CSetting::TYPE_STRING,IDS_SEARCH_COMMAND,IDS_SEARCH_COMMAND_TIP,L"search-ms:",CSetting::FLAG_MENU_CLASSIC_BOTH}, {L"ExpandFolderLinks",CSetting::TYPE_BOOL,IDS_EXPAND_LINKS,IDS_EXPAND_LINKS_TIP,1}, + {L"SingleClickFolders",CSetting::TYPE_BOOL,IDS_NO_DBLCLICK,IDS_NO_DBLCLICK_TIP,0}, {L"EnableTouch",CSetting::TYPE_BOOL,IDS_ENABLE_TOUCH,IDS_ENABLE_TOUCH_TIP,1}, {L"EnableAccessibility",CSetting::TYPE_BOOL,IDS_ACCESSIBILITY,IDS_ACCESSIBILITY_TIP,1}, {L"ShowNextToTaskbar",CSetting::TYPE_BOOL,IDS_NEXTTASKBAR,IDS_NEXTTASKBAR_TIP,0}, diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc index 405d5aa1f..6e35344b4 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc @@ -1295,6 +1295,12 @@ BEGIN IDS_CLEAR_CACHE "Clear cached information" END +STRINGTABLE +BEGIN + IDS_NO_DBLCLICK "Single-click to open folder shortcuts" + IDS_NO_DBLCLICK_TIP "When this is checked, single-clicking shortcuts (links) to folders will open them in explorer. Hovering over the shortcut will still expand sub-menus" +END + #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/Src/StartMenu/StartMenuDLL/resource.h b/Src/StartMenu/StartMenuDLL/resource.h index ca08926ca..2d365081c 100644 --- a/Src/StartMenu/StartMenuDLL/resource.h +++ b/Src/StartMenu/StartMenuDLL/resource.h @@ -760,6 +760,8 @@ #define IDS_HOR_OFFSET_TIP 3663 #define IDS_VERT_OFFSET 3664 #define IDS_VERT_OFFSET_TIP 3665 +#define IDS_NO_DBLCLICK 3666 +#define IDS_NO_DBLCLICK_TIP 3667 #define IDS_STRING7001 7001 #define IDS_STRING7002 7002 #define IDS_STRING7003 7003 From 998d83c15c1fe753526a43fb4c182a4b25e83252 Mon Sep 17 00:00:00 2001 From: thisismy-github <48284263+thisismy-github@users.noreply.github.com> Date: Thu, 12 Aug 2021 09:14:19 -0400 Subject: [PATCH 002/155] Auto-detect when setting is back to default value Intercepts *most* instances of FLAG_DEFAULT getting set, including when XML files are loaded and when Open-Shell starts, adding if-statements to those spots to check if a new value is actually different from the setting's default value. Ensures more consistency behind the scenes and gets rid of inaccurate bold highlights. --- Src/Lib/Settings.cpp | 20 +++++-- Src/Lib/SettingsUIHelper.cpp | 35 +++++++++--- Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 65 ++++++++++++++++++----- 3 files changed, 96 insertions(+), 24 deletions(-) diff --git a/Src/Lib/Settings.cpp b/Src/Lib/Settings.cpp index df9646f4e..7b0d456a1 100644 --- a/Src/Lib/Settings.cpp +++ b/Src/Lib/Settings.cpp @@ -793,7 +793,10 @@ CString CSettingsManager::LoadSettingsXml( const wchar_t *fname ) } string.push_back(0); pSetting->value=CComVariant(&string[0]); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; } else { @@ -806,7 +809,10 @@ CString CSettingsManager::LoadSettingsXml( const wchar_t *fname ) if (pSetting->type>=CSetting::TYPE_STRING) { pSetting->value=value; - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; } else if (pSetting->type==CSetting::TYPE_BOOL || (pSetting->type==CSetting::TYPE_INT && pSetting[1].type!=CSetting::TYPE_RADIO) || pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY || pSetting->type==CSetting::TYPE_COLOR) { @@ -815,7 +821,10 @@ CString CSettingsManager::LoadSettingsXml( const wchar_t *fname ) pSetting->value=CComVariant(val?1:0); else pSetting->value=CComVariant(val); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; } else if (pSetting->type==CSetting::TYPE_INT && pSetting[1].type==CSetting::TYPE_RADIO) { @@ -825,7 +834,10 @@ CString CSettingsManager::LoadSettingsXml( const wchar_t *fname ) if (_wcsicmp(pRadio->name,value.bstrVal)==0) { pSetting->value=CComVariant(val); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; break; } } diff --git a/Src/Lib/SettingsUIHelper.cpp b/Src/Lib/SettingsUIHelper.cpp index 05e2c03ad..e201720a2 100644 --- a/Src/Lib/SettingsUIHelper.cpp +++ b/Src/Lib/SettingsUIHelper.cpp @@ -1822,7 +1822,10 @@ void CCustomTreeDlg::SerializeData( void ) if ((m_pSetting->flags&CSetting::FLAG_DEFAULT) || wcscmp(strNew,strOld)!=0) SetSettingsDirty(); m_pSetting->value=CComVariant(strNew); - m_pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (m_pSetting->value==m_pSetting->defValue) + m_pSetting->flags|=CSetting::FLAG_DEFAULT; + else + m_pSetting->flags&=~CSetting::FLAG_DEFAULT; ItemsChanged(); } @@ -2778,7 +2781,10 @@ void CTreeSettingsDlg::ToggleItem( HTREEITEM hItem, bool bDefault ) { CSettingsLockWrite lock; pSetting->value=CComVariant(state?0:1); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; SetSettingsDirty(); } if (pSetting->flags&CSetting::FLAG_CALLBACK) @@ -2802,7 +2808,10 @@ void CTreeSettingsDlg::ToggleItem( HTREEITEM hItem, bool bDefault ) { CSettingsLockWrite lock; pTarget->value=CComVariant(val); - pTarget->flags&=~CSetting::FLAG_DEFAULT; + if (pTarget->value==pTarget->defValue) + pTarget->flags|=CSetting::FLAG_DEFAULT; + else + pTarget->flags&=~CSetting::FLAG_DEFAULT; SetSettingsDirty(); } if (pParent->flags&CSetting::FLAG_CALLBACK) @@ -3013,7 +3022,10 @@ void CTreeSettingsDlg::ApplyEditBox( void ) if (pSetting->value.vt!=VT_I4 || pSetting->value.intVal!=val) { pSetting->value=CComVariant(val); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; } } else if (pSetting->type==CSetting::TYPE_COLOR) @@ -3023,7 +3035,10 @@ void CTreeSettingsDlg::ApplyEditBox( void ) if (pSetting->value.vt!=VT_I4 || pSetting->value.intVal!=val) { pSetting->value=CComVariant(val); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; } } else if (pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY) @@ -3031,7 +3046,10 @@ void CTreeSettingsDlg::ApplyEditBox( void ) if (pSetting->value.vt!=VT_I4 || pSetting->value.intVal!=g_HotKey) { pSetting->value=CComVariant(g_HotKey); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; } } else @@ -3039,7 +3057,10 @@ void CTreeSettingsDlg::ApplyEditBox( void ) if (pSetting->value.vt!=VT_BSTR || str!=pSetting->value.bstrVal) { pSetting->value=CComVariant(str); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; } } SetSettingsDirty(); diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index 8a7b7b240..aa0ee5d83 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -3616,7 +3616,10 @@ void CCustomMenuDlg7::SerializeData( void ) stringBuilder.push_back(0); CSettingsLockWrite lock; m_pSetting->value=CComVariant(&stringBuilder[0]); - m_pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (m_pSetting->value==m_pSetting->defValue) + m_pSetting->flags|=CSetting::FLAG_DEFAULT; + else + m_pSetting->flags&=~CSetting::FLAG_DEFAULT; SetSettingsDirty(); } @@ -3843,7 +3846,10 @@ LRESULT CMenuStyleDlg::OnClick( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& CheckDlgButton(IDC_RADIO_CLASSIC,pSetting->value.intVal==MENU_CLASSIC1?BST_CHECKED:BST_UNCHECKED); CheckDlgButton(IDC_RADIO_TWO_COLUMNS,pSetting->value.intVal==MENU_CLASSIC2?BST_CHECKED:BST_UNCHECKED); CheckDlgButton(IDC_RADIO_WIN7,pSetting->value.intVal==MENU_WIN7?BST_CHECKED:BST_UNCHECKED); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; SetSettingsDirty(); SetSettingsStyle(styleFlag,CSetting::FLAG_MENU_MASK); @@ -3861,7 +3867,10 @@ LRESULT CMenuStyleDlg::OnEnabled( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL CSettingsLockWrite lock; CSetting *pSetting=FindSetting(L"EnableStartButton"); pSetting->value=CComVariant(bEnabled); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; SetSettingsDirty(); } Update(false); @@ -3900,7 +3909,10 @@ LRESULT CMenuStyleDlg::OnButtonStyle( WORD wNotifyCode, WORD wID, HWND hWndCtl, CSettingsLockWrite lock; CSetting *pSetting=FindSetting(L"StartButtonType"); pSetting->value=CComVariant(style); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; SetSettingsDirty(); } Update(false); @@ -3924,7 +3936,10 @@ LRESULT CMenuStyleDlg::OnPick( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& b CSettingsLockWrite lock; CSetting *pSetting=FindSetting(L"StartButtonPath"); pSetting->value=CComVariant(path); - pSetting->flags&=~CSetting::FLAG_DEFAULT; + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; SetSettingsDirty(); } Update(true); @@ -4545,7 +4560,10 @@ void UpgradeSettings( bool bShared ) items.Replace(L"Command=recent_items\n",L"Command=recent_programs\n"); items.Replace(L"Command=control_panel_categories\n",L"Command=control_panel\n"); pSettingItems->value=items; - pSettingItems->flags&=~CSetting::FLAG_DEFAULT; + if (pSettingItems->value==pSettingItems->defValue) + pSettingItems->flags|=CSetting::FLAG_DEFAULT; + else + pSettingItems->flags&=~CSetting::FLAG_DEFAULT; } // set initial menu style @@ -4553,7 +4571,10 @@ void UpgradeSettings( bool bShared ) if (!pSettingStyle->IsLocked()) { pSettingStyle->value=(bTwoColumns?1:0); - pSettingStyle->flags&=~CSetting::FLAG_DEFAULT; + if (pSettingStyle->value==pSettingStyle->defValue) + pSettingStyle->flags|=CSetting::FLAG_DEFAULT; + else + pSettingStyle->flags&=~CSetting::FLAG_DEFAULT; SetSettingsStyle(bTwoColumns?CSetting::FLAG_MENU_CLASSIC2:CSetting::FLAG_MENU_CLASSIC1,CSetting::FLAG_MENU_MASK); } @@ -4565,7 +4586,10 @@ void UpgradeSettings( bool bShared ) if (!pSetting->IsDefault()) { pSettingSkin->value=pSetting->value; - pSettingSkin->flags&=~CSetting::FLAG_DEFAULT; + if (pSettingSkin->value==pSettingSkin->defValue) + pSettingSkin->flags|=CSetting::FLAG_DEFAULT; + else + pSettingSkin->flags&=~CSetting::FLAG_DEFAULT; } } CSetting *pSettingOpt=FindSetting(bTwoColumns?L"SkinOptionsC2":L"SkinOptionsC1"); @@ -4575,7 +4599,10 @@ void UpgradeSettings( bool bShared ) if (!pSetting->IsDefault()) { pSettingOpt->value=pSetting->value; - pSettingOpt->flags&=~CSetting::FLAG_DEFAULT; + if (pSettingOpt->value==pSettingOpt->defValue) + pSettingOpt->flags|=CSetting::FLAG_DEFAULT; + else + pSettingOpt->flags&=~CSetting::FLAG_DEFAULT; } } CSetting *pSettingVar=FindSetting(bTwoColumns?L"SkinVariationC2":L"SkinVariationC1"); @@ -4585,7 +4612,10 @@ void UpgradeSettings( bool bShared ) if (!pSetting->IsDefault()) { pSettingVar->value=pSetting->value; - pSettingVar->flags&=~CSetting::FLAG_DEFAULT; + if (pSettingVar->value==pSettingVar->defValue) + pSettingVar->flags|=CSetting::FLAG_DEFAULT; + else + pSettingVar->flags&=~CSetting::FLAG_DEFAULT; } } @@ -4597,7 +4627,10 @@ void UpgradeSettings( bool bShared ) if (!pSetting->IsDefault()) { pSettingSkin->value=pSetting->value; - pSettingSkin->flags&=~CSetting::FLAG_DEFAULT; + if (pSettingSkin->value==pSettingSkin->defValue) + pSettingSkin->flags|=CSetting::FLAG_DEFAULT; + else + pSettingSkin->flags&=~CSetting::FLAG_DEFAULT; } } pSettingOpt=FindSetting(L"SkinOptionsA"); @@ -4607,7 +4640,10 @@ void UpgradeSettings( bool bShared ) if (!pSetting->IsDefault()) { pSettingOpt->value=pSetting->value; - pSettingOpt->flags&=~CSetting::FLAG_DEFAULT; + if (pSettingOpt->value==pSettingOpt->defValue) + pSettingOpt->flags|=CSetting::FLAG_DEFAULT; + else + pSettingOpt->flags&=~CSetting::FLAG_DEFAULT; } } pSettingVar=FindSetting(L"SkinVariationA"); @@ -4617,7 +4653,10 @@ void UpgradeSettings( bool bShared ) if (!pSetting->IsDefault()) { pSettingVar->value=pSetting->value; - pSettingVar->flags&=~CSetting::FLAG_DEFAULT; + if (pSettingVar->value==pSettingVar->defValue) + pSettingVar->flags|=CSetting::FLAG_DEFAULT; + else + pSettingVar->flags&=~CSetting::FLAG_DEFAULT; } } } From daa1d96f12be9c9d6d77865c0d1f6439b6f2f34b Mon Sep 17 00:00:00 2001 From: thisismy-github <48284263+thisismy-github@users.noreply.github.com> Date: Thu, 12 Aug 2021 14:28:07 -0400 Subject: [PATCH 003/155] Added option to never highlight modified settings Prevents settings from appearing in bold. Does not change the helper text at the bottom of the window. --- Src/Lib/SettingsUIHelper.cpp | 5 ++++- Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 1 + Src/StartMenu/StartMenuDLL/StartMenuDLL.rc | 2 ++ Src/StartMenu/StartMenuDLL/resource.h | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Src/Lib/SettingsUIHelper.cpp b/Src/Lib/SettingsUIHelper.cpp index e201720a2..0c3221223 100644 --- a/Src/Lib/SettingsUIHelper.cpp +++ b/Src/Lib/SettingsUIHelper.cpp @@ -3397,6 +3397,9 @@ void CTreeSettingsDlg::UpdateGroup( const CSetting *pModified ) bool bDefault=pSetting->IsDefault(); const CComVariant &valVar=pSetting->GetValue(); + // check if modified items should be bold + bool bBoldSettings=GetSettingBool(L"BoldSettings"); + // calculate text if (pSetting!=m_pEditSetting) { @@ -3479,7 +3482,7 @@ void CTreeSettingsDlg::UpdateGroup( const CSetting *pModified ) DeleteDC(hdc); DeleteDC(hdcMask); } - int state=bDefault?0:TVIS_BOLD; + int state=bDefault||!bBoldSettings?0:TVIS_BOLD; // check if item should be highlighted in bold if (!bEnabled) { if (pSetting->type!=CSetting::TYPE_COLOR) image|=SETTING_STATE_DISABLED; diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index aa0ee5d83..68eea85fd 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -4334,6 +4334,7 @@ CSetting g_Settings[]={ {L"ShowNextToTaskbar",CSetting::TYPE_BOOL,IDS_NEXTTASKBAR,IDS_NEXTTASKBAR_TIP,0}, {L"PreCacheIcons",CSetting::TYPE_BOOL,IDS_CACHE_ICONS,IDS_CACHE_ICONS_TIP,1,CSetting::FLAG_COLD}, {L"DelayIcons",CSetting::TYPE_BOOL,IDS_DELAY_ICONS,IDS_DELAY_ICONS_TIP,1,CSetting::FLAG_COLD}, + {L"BoldSettings",CSetting::TYPE_BOOL,IDS_BOLD_SETTINGS,IDS_BOLD_SETTINGS_TIP,1}, {L"ReportSkinErrors",CSetting::TYPE_BOOL,IDS_SKIN_ERRORS,IDS_SKIN_ERRORS_TIP,0}, {L"SearchBoxSettings",CSetting::TYPE_GROUP,IDS_SEARCH_BOX}, diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc index 6e35344b4..f8b56f6fc 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc @@ -1299,6 +1299,8 @@ STRINGTABLE BEGIN IDS_NO_DBLCLICK "Single-click to open folder shortcuts" IDS_NO_DBLCLICK_TIP "When this is checked, single-clicking shortcuts (links) to folders will open them in explorer. Hovering over the shortcut will still expand sub-menus" + IDS_BOLD_SETTINGS "Highlight modified settings" + IDS_BOLD_SETTINGS_TIP "When this is checked, settings that have been modified from their defaults will be highlighted in bold" END #endif // English (U.S.) resources diff --git a/Src/StartMenu/StartMenuDLL/resource.h b/Src/StartMenu/StartMenuDLL/resource.h index 2d365081c..0d33c1c15 100644 --- a/Src/StartMenu/StartMenuDLL/resource.h +++ b/Src/StartMenu/StartMenuDLL/resource.h @@ -762,6 +762,8 @@ #define IDS_VERT_OFFSET_TIP 3665 #define IDS_NO_DBLCLICK 3666 #define IDS_NO_DBLCLICK_TIP 3667 +#define IDS_BOLD_SETTINGS 3668 +#define IDS_BOLD_SETTINGS_TIP 3669 #define IDS_STRING7001 7001 #define IDS_STRING7002 7002 #define IDS_STRING7003 7003 From 68379f40985894b3baf5851cc6cf38caa577521d Mon Sep 17 00:00:00 2001 From: thisismy-github <48284263+thisismy-github@users.noreply.github.com> Date: Thu, 12 Aug 2021 15:31:42 -0400 Subject: [PATCH 004/155] Fixed bug between XML files and active edit boxes When loading XML files, settings with active edit boxes open will not be adjusted. This adds an additional tab-reload before the load begins to forcibly close any active edit boxes. --- Src/Lib/Settings.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Src/Lib/Settings.cpp b/Src/Lib/Settings.cpp index 7b0d456a1..fb312fc8b 100644 --- a/Src/Lib/Settings.cpp +++ b/Src/Lib/Settings.cpp @@ -1713,6 +1713,7 @@ LRESULT CSettingsDlg::OnBackup( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& ofn.Flags=OFN_DONTADDTORECENT|OFN_ENABLESIZING|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|OFN_NOCHANGEDIR; if (GetOpenFileName(&ofn)) { + SetCurTab(m_Index,true); // reload tab once to force-close any active edit boxes CString error=g_SettingsManager.LoadSettingsXml(path); if (!error.IsEmpty()) { @@ -1722,7 +1723,7 @@ LRESULT CSettingsDlg::OnBackup( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& ::MessageBox(m_hWnd,text,LoadStringEx(IDS_ERROR_TITLE),MB_OK|MB_ICONERROR); } SetSettingsDirty(); - SetCurTab(m_Index,true); + SetCurTab(m_Index,true); // reload tab again to show the new settings } } if (res==3) From 5399e3ad8cc05170c2d0c5e1bd06496f6c88b672 Mon Sep 17 00:00:00 2001 From: thisismy-github <48284263+thisismy-github@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:32:15 -0400 Subject: [PATCH 005/155] Added option to use a custom search hint If set, intercepts the search hint's DrawText function and swaps out the default text for user-defined text. Leaving the text blank results in an empty search box. --- Src/StartMenu/StartMenuDLL/MenuContainer.cpp | 5 ++++- Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 2 ++ Src/StartMenu/StartMenuDLL/StartMenuDLL.rc | 4 ++++ Src/StartMenu/StartMenuDLL/resource.h | 4 ++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp index 8fc20af43..78915f4c9 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp @@ -444,7 +444,10 @@ LRESULT CALLBACK CMenuContainer::SubclassSearchBox( HWND hWnd, UINT uMsg, WPARAM SetBkColor(hdc,GetSysColor(COLOR_WINDOW)); SetBkMode(hdc,TRANSPARENT); SetTextColor(hdc,s_Skin.Search_text_colors[1]); - DrawText(hdc,pParent->m_Items[pParent->m_SearchIndex].name,-1,&rc,DT_SINGLELINE|DT_EDITCONTROL|(s_bRTL?DT_RIGHT:DT_LEFT)); + if (GetSettingBool(L"SearchHint")) + DrawText(hdc,GetSettingString(L"SearchHintText"),-1,&rc,DT_SINGLELINE|DT_EDITCONTROL|(s_bRTL?DT_RIGHT:DT_LEFT)); + else + DrawText(hdc,pParent->m_Items[pParent->m_SearchIndex].name,-1,&rc,DT_SINGLELINE|DT_EDITCONTROL|(s_bRTL?DT_RIGHT:DT_LEFT)); SelectObject(hdc,font0); } return res; diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index 68eea85fd..de0b5157f 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -4343,6 +4343,8 @@ CSetting g_Settings[]={ {L"Normal",CSetting::TYPE_RADIO,IDS_SEARCH_BOX_SHOW,IDS_SEARCH_BOX_SHOW_TIP}, {L"Tab",CSetting::TYPE_RADIO,IDS_SEARCH_BOX_TAB,IDS_SEARCH_BOX_TAB_TIP}, {L"SearchSelect",CSetting::TYPE_BOOL,IDS_SEARCH_BOX_SEL,IDS_SEARCH_BOX_SEL_TIP,1,0,L"SearchBox=1",L"Normal"}, + {L"SearchHint",CSetting::TYPE_BOOL,IDS_SEARCH_HINT,IDS_SEARCH_HINT_TIP,0,0,L"SearchBox"}, + {L"SearchHintText",CSetting::TYPE_STRING,IDS_NEW_SEARCH_HINT,IDS_NEW_SEARCH_HINT_TIP,L"",0,L"#SearchHint",L"SearchHint"}, {L"SearchTrack",CSetting::TYPE_BOOL,IDS_SEARCH_TRACK,IDS_SEARCH_TRACK_TIP,1,0,L"SearchBox"}, {L"SearchResults",CSetting::TYPE_INT,IDS_SEARCH_MAX2,IDS_SEARCH_MAX_TIP2,5,CSetting::FLAG_MENU_CLASSIC_BOTH,L"SearchBox"}, {L"SearchResultsMax",CSetting::TYPE_INT,IDS_SEARCH_MAX3,IDS_SEARCH_MAX_TIP3,20,CSetting::FLAG_MENU_CLASSIC_BOTH,L"SearchBox"}, diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc index f8b56f6fc..daf0a68fe 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc @@ -1301,6 +1301,10 @@ BEGIN IDS_NO_DBLCLICK_TIP "When this is checked, single-clicking shortcuts (links) to folders will open them in explorer. Hovering over the shortcut will still expand sub-menus" IDS_BOLD_SETTINGS "Highlight modified settings" IDS_BOLD_SETTINGS_TIP "When this is checked, settings that have been modified from their defaults will be highlighted in bold" + IDS_SEARCH_HINT "Custom search hint" + IDS_SEARCH_HINT_TIP "When this is checked, the hint text in the search box will be replaced" + IDS_NEW_SEARCH_HINT "Custom search hint text" + IDS_NEW_SEARCH_HINT_TIP "The text to replace the search hint with. Empty text is a valid option" END #endif // English (U.S.) resources diff --git a/Src/StartMenu/StartMenuDLL/resource.h b/Src/StartMenu/StartMenuDLL/resource.h index 0d33c1c15..1adc21d8a 100644 --- a/Src/StartMenu/StartMenuDLL/resource.h +++ b/Src/StartMenu/StartMenuDLL/resource.h @@ -764,6 +764,10 @@ #define IDS_NO_DBLCLICK_TIP 3667 #define IDS_BOLD_SETTINGS 3668 #define IDS_BOLD_SETTINGS_TIP 3669 +#define IDS_SEARCH_HINT 3670 +#define IDS_SEARCH_HINT_TIP 3671 +#define IDS_NEW_SEARCH_HINT 3672 +#define IDS_NEW_SEARCH_HINT_TIP 3673 #define IDS_STRING7001 7001 #define IDS_STRING7002 7002 #define IDS_STRING7003 7003 From be8568ce0091a4573198e4f818a012621f8ae9e9 Mon Sep 17 00:00:00 2001 From: thisismy-github <48284263+thisismy-github@users.noreply.github.com> Date: Thu, 12 Aug 2021 17:59:00 -0400 Subject: [PATCH 006/155] Added option to hide "see more results" in search Hides the item in both start menu styles and adjusts search height to ensure the empty space is used. Partially fixes #660, but currently does not honor group policy settings. --- Src/StartMenu/StartMenuDLL/MenuContainer.cpp | 39 +++++++++++--------- Src/StartMenu/StartMenuDLL/MenuContainer.h | 1 + Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 1 + Src/StartMenu/StartMenuDLL/StartMenuDLL.rc | 2 + Src/StartMenu/StartMenuDLL/resource.h | 2 + 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp index 78915f4c9..b20452a8c 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp @@ -335,6 +335,7 @@ bool CMenuContainer::s_bDragMovable; bool CMenuContainer::s_bRightDrag; bool CMenuContainer::s_bLockWorkArea; bool CMenuContainer::s_bPendingSearchEnter; +bool CMenuContainer::s_bMoreResults; std::vector CMenuContainer::s_Menus; volatile HWND CMenuContainer::s_FirstMenu, CMenuContainer::s_SearchMenu; CSearchManager::SearchResults CMenuContainer::s_SearchResults; @@ -2745,9 +2746,9 @@ bool CMenuContainer::InitSearchItems( void ) { sepHeight=s_Skin.ItemSettings[s_Skin.More_bitmap_Size.cx?MenuSkin::LIST_SEPARATOR_SPLIT:MenuSkin::LIST_SEPARATOR].itemHeight; itemHeight=s_Skin.ItemSettings[MenuSkin::LIST_ITEM].itemHeight; - // total height minus the search box and the "more results"/"search internet" + // total height minus the search box and the "more results"/"search internet", if present maxHeight=m_Items[m_SearchIndex].itemRect.top-s_Skin.Main_search_padding.top-s_Skin.Search_padding.top; - maxHeight-=itemHeight*(m_SearchItemCount-1); + maxHeight-=itemHeight*(m_SearchItemCount-(s_bMoreResults?1:2)); if (!s_SearchResults.bSearching && !HasMoreResults()) maxHeight+=itemHeight; } @@ -2941,25 +2942,28 @@ bool CMenuContainer::InitSearchItems( void ) if (s_bWin7Style) { UpdateAccelerators(m_OriginalCount,(int)m_Items.size()); - MenuItem &item=m_Items[m_SearchIndex-m_SearchItemCount+1]; - if (s_SearchResults.bSearching) + if (s_bMoreResults) { - item.id=MENU_SEARCH_EMPTY; - item.name=FindTranslation(L"Menu.Searching",L"Searching..."); - item.pItemInfo=g_ItemManager.GetCustomIcon(L"imageres.dll,8",CItemManager::ICON_SIZE_TYPE_SMALL); - } - else - { - item.id=MENU_MORE_RESULTS; - item.name=FindTranslation(L"Menu.MoreResults",L"See more results"); - item.pItemInfo=g_ItemManager.GetCustomIcon(L"imageres.dll,177",CItemManager::ICON_SIZE_TYPE_SMALL); + MenuItem &item=m_Items[m_SearchIndex-m_SearchItemCount+1]; + if (s_SearchResults.bSearching) + { + item.id=MENU_SEARCH_EMPTY; + item.name=FindTranslation(L"Menu.Searching",L"Searching..."); + item.pItemInfo=g_ItemManager.GetCustomIcon(L"imageres.dll,8",CItemManager::ICON_SIZE_TYPE_SMALL); + } + else + { + item.id=MENU_MORE_RESULTS; + item.name=FindTranslation(L"Menu.MoreResults",L"See more results"); + item.pItemInfo=g_ItemManager.GetCustomIcon(L"imageres.dll,177",CItemManager::ICON_SIZE_TYPE_SMALL); + } } } else { m_ScrollCount=(int)m_Items.size(); - bool bInternet=GetSettingBool(L"SearchInternet"); - if (s_SearchResults.bSearching) + bool bInternet=GetSettingBool(L"SearchInternet"); + if (s_bMoreResults && s_SearchResults.bSearching) { MenuItem item(MENU_SEARCH_EMPTY); item.name=FindTranslation(L"Menu.Searching",L"Searching..."); @@ -2974,7 +2978,7 @@ bool CMenuContainer::InitSearchItems( void ) item.name=FindTranslation(L"Menu.NoMatch",L"No items match your search."); m_Items.push_back(item); } - if (HasMoreResults()) + if (s_bMoreResults && HasMoreResults()) { { MenuItem item(MENU_SEPARATOR); @@ -5062,7 +5066,7 @@ void CMenuContainer::UpdateSearchResults( bool bForceShowAll ) g_SearchManager.BeginSearch(s_SearchResults.currentString); s_SearchResults.bSearching=true; s_bPendingSearchEnter=false; - if (s_bWin7Style) + if (s_bWin7Style && s_bMoreResults) { MenuItem &item=m_Items[m_SearchIndex-m_SearchItemCount+1]; item.id=MENU_SEARCH_EMPTY; @@ -7694,6 +7698,7 @@ HWND CMenuContainer::ToggleStartMenu( int taskbarId, bool bKeyboard, bool bAllPr s_bDisableHover=false; s_bDragClosed=false; s_bPendingSearchEnter=false; + s_bMoreResults=GetSettingBool(L"MoreResults"); InitTouchHelper(); bool bRemote=GetSystemMetrics(SM_REMOTESESSION)!=0; diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.h b/Src/StartMenu/StartMenuDLL/MenuContainer.h index ad34beb27..84e36931c 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.h +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.h @@ -896,6 +896,7 @@ class CMenuContainer: public IDropTarget, public IFrameworkInputPaneHandler, pub static bool s_bRightDrag; // dragging with the right mouse button static bool s_bLockWorkArea; // changes to the work area are ignored static bool s_bPendingSearchEnter; // Enter was pressed before the search results were ready + static bool s_bMoreResults; // shows the "Show More Results" item at the bottom of searches static RECT s_MenuLimits; // area of the main monitor accessible to all menus static RECT s_MainMenuLimits; // area of the main monitor accessible by the main menu static DWORD s_TaskbarState; // the state of the taskbar (ABS_AUTOHIDE and ABS_ALWAYSONTOP) diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index de0b5157f..a037dfe69 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -4359,6 +4359,7 @@ CSetting g_Settings[]={ {L"SearchContents",CSetting::TYPE_BOOL,IDS_SEARCH_CONTENTS,IDS_SEARCH_CONTENTS_TIP,1,0,L"#SearchFiles",L"SearchFiles"}, {L"SearchCategories",CSetting::TYPE_BOOL,IDS_SEARCH_CATEGORIES,IDS_SEARCH_CATEGORIES_TIP,1,0,L"#SearchFiles",L"SearchFiles"}, {L"SearchInternet",CSetting::TYPE_BOOL,IDS_SEARCH_INTERNET,IDS_SEARCH_INTERNET_TIP,1,0,L"SearchBox"}, + {L"MoreResults",CSetting::TYPE_BOOL,IDS_MORE_RESULTS,IDS_MORE_RESULTS_TIP,1,0,L"SearchBox"}, {L"Look",CSetting::TYPE_GROUP,IDS_LOOK_SETTINGS}, {L"SmallIconSize",CSetting::TYPE_INT,IDS_SMALL_SIZE_SM,IDS_SMALL_SIZE_SM_TIP,-1,CSetting::FLAG_COLD}, // 16 for DPI<=96, 20 for DPI<=120, 24 otherwise diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc index daf0a68fe..c857c0e20 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc @@ -1305,6 +1305,8 @@ BEGIN IDS_SEARCH_HINT_TIP "When this is checked, the hint text in the search box will be replaced" IDS_NEW_SEARCH_HINT "Custom search hint text" IDS_NEW_SEARCH_HINT_TIP "The text to replace the search hint with. Empty text is a valid option" + IDS_MORE_RESULTS "Enable ""See more results"" option" + IDS_MORE_RESULTS_TIP "When this is checked, the search results will include an option to do a more advanced search" END #endif // English (U.S.) resources diff --git a/Src/StartMenu/StartMenuDLL/resource.h b/Src/StartMenu/StartMenuDLL/resource.h index 1adc21d8a..daeabf246 100644 --- a/Src/StartMenu/StartMenuDLL/resource.h +++ b/Src/StartMenu/StartMenuDLL/resource.h @@ -768,6 +768,8 @@ #define IDS_SEARCH_HINT_TIP 3671 #define IDS_NEW_SEARCH_HINT 3672 #define IDS_NEW_SEARCH_HINT_TIP 3673 +#define IDS_MORE_RESULTS 3674 +#define IDS_MORE_RESULTS_TIP 3675 #define IDS_STRING7001 7001 #define IDS_STRING7002 7002 #define IDS_STRING7003 7003 From ef663d2051956ed7e6405b2be82cde2b4e4bf877 Mon Sep 17 00:00:00 2001 From: thisismy-github <48284263+thisismy-github@users.noreply.github.com> Date: Sat, 14 Aug 2021 21:19:32 -0400 Subject: [PATCH 007/155] Added option to set custom commands for controls Includes a unique option for each control and supports environment variables. --- Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 12 +++++ Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp | 51 +++++++++++++++++++++ Src/StartMenu/StartMenuDLL/StartMenuDLL.rc | 4 ++ Src/StartMenu/StartMenuDLL/resource.h | 4 ++ 4 files changed, 71 insertions(+) diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index a037dfe69..ac9c606d9 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -4154,38 +4154,50 @@ CSetting g_Settings[]={ {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"Command",CSetting::TYPE_RADIO,IDS_OPEN_CMD,IDS_OPEN_CMD_TIP}, {L"Both",CSetting::TYPE_RADIO,IDS_OPEN_BOTH,IDS_OPEN_BOTH_TIP,0,CSetting::FLAG_HIDDEN}, + {L"MouseClickCommand",CSetting::TYPE_STRING,IDS_OPEN_CMD_TEXT,IDS_OPEN_CMD_TEXT_TIP,"%userprofile%",0,L"MouseClick=3",L"Command"}, {L"ShiftClick",CSetting::TYPE_INT,IDS_SHIFT_LCLICK,IDS_SHIFT_LCLICK_TIP,2,CSetting::FLAG_BASIC}, {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"Command",CSetting::TYPE_RADIO,IDS_OPEN_CMD,IDS_OPEN_CMD_TIP}, {L"Both",CSetting::TYPE_RADIO,IDS_OPEN_BOTH,IDS_OPEN_BOTH_TIP,0,CSetting::FLAG_HIDDEN}, /* {L"Desktop",CSetting::TYPE_RADIO,IDS_OPEN_DESKTOP,IDS_OPEN_DESKTOP_TIP,0,CSetting::FLAG_HIDDEN}, {L"Cortana",CSetting::TYPE_RADIO,IDS_OPEN_CORTANA,IDS_OPEN_CORTANA_TIP},*/ + {L"ShiftClickCommand",CSetting::TYPE_STRING,IDS_OPEN_CMD_TEXT,IDS_OPEN_CMD_TEXT_TIP,"%systemdrive%",0,L"ShiftClick=3",L"Command"}, {L"WinKey",CSetting::TYPE_INT,IDS_WIN_KEY,IDS_WIN_KEY_TIP,1,CSetting::FLAG_BASIC}, {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"Command",CSetting::TYPE_RADIO,IDS_OPEN_CMD,IDS_OPEN_CMD_TIP}, {L"Both",CSetting::TYPE_RADIO,IDS_OPEN_BOTH,IDS_OPEN_BOTH_TIP}, {L"Desktop",CSetting::TYPE_RADIO,IDS_OPEN_DESKTOP,IDS_OPEN_DESKTOP_TIP}, + {L"WinKeyCommand",CSetting::TYPE_STRING,IDS_OPEN_CMD_TEXT,IDS_OPEN_CMD_TEXT_TIP,"cmd",0,L"WinKey=3",L"Command"}, {L"ShiftWin",CSetting::TYPE_INT,IDS_SHIFT_WIN,IDS_SHIFT_WIN_TIP,2,CSetting::FLAG_BASIC}, {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"Command",CSetting::TYPE_RADIO,IDS_OPEN_CMD,IDS_OPEN_CMD_TIP}, {L"Both",CSetting::TYPE_RADIO,IDS_OPEN_BOTH,IDS_OPEN_BOTH_TIP}, /* {L"Desktop",CSetting::TYPE_RADIO,IDS_OPEN_DESKTOP,IDS_OPEN_DESKTOP_TIP,0,CSetting::FLAG_HIDDEN}, {L"Cortana",CSetting::TYPE_RADIO,IDS_OPEN_CORTANA,IDS_OPEN_CORTANA_TIP},*/ + {L"ShiftWinCommand",CSetting::TYPE_STRING,IDS_OPEN_CMD_TEXT,IDS_OPEN_CMD_TEXT_TIP,"powershell",0,L"ShiftWin=3",L"Command"}, {L"MiddleClick",CSetting::TYPE_INT,IDS_MCLICK,IDS_MCLICK_TIP,0}, {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"Command",CSetting::TYPE_RADIO,IDS_OPEN_CMD,IDS_OPEN_CMD_TIP}, /* {L"Both",CSetting::TYPE_RADIO,IDS_OPEN_BOTH,IDS_OPEN_BOTH_TIP,0,CSetting::FLAG_HIDDEN}, {L"Desktop",CSetting::TYPE_RADIO,IDS_OPEN_DESKTOP,IDS_OPEN_DESKTOP_TIP,0,CSetting::FLAG_HIDDEN}, {L"Cortana",CSetting::TYPE_RADIO,IDS_OPEN_CORTANA,IDS_OPEN_CORTANA_TIP},*/ + {L"MiddleClickCommand",CSetting::TYPE_STRING,IDS_OPEN_CMD_TEXT,IDS_OPEN_CMD_TEXT_TIP,"taskmgr",0,L"MiddleClick=3",L"Command"}, {L"Hover",CSetting::TYPE_INT,IDS_HOVER,IDS_HOVER_TIP,0}, {L"Nothing",CSetting::TYPE_RADIO,IDS_OPEN_NOTHING,IDS_OPEN_NOTHING_TIP}, {L"ClassicMenu",CSetting::TYPE_RADIO,IDS_OPEN_CSM,IDS_OPEN_CSM_TIP}, {L"WindowsMenu",CSetting::TYPE_RADIO,IDS_OPEN_WSM,IDS_OPEN_WSM_TIP}, + {L"Command",CSetting::TYPE_RADIO,IDS_OPEN_CMD,IDS_OPEN_CMD_TIP}, + {L"HoverCommand",CSetting::TYPE_STRING,IDS_OPEN_CMD_TEXT,IDS_OPEN_CMD_TEXT_TIP,"",0,L"Hover=3",L"Command"}, {L"StartHoverDelay",CSetting::TYPE_INT,IDS_HOVER_DELAY,IDS_HOVER_DELAY_TIP,1000,0,L"Hover",L"Hover"}, {L"ShiftRight",CSetting::TYPE_BOOL,IDS_RIGHT_SHIFT,IDS_RIGHT_SHIFT_TIP,0}, {L"CSMHotkey",CSetting::TYPE_HOTKEY,IDS_CSM_HOTKEY,IDS_CSM_HOTKEY_TIP,0}, diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp b/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp index fa5bc3e5c..feef6452d 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp @@ -79,6 +79,7 @@ enum OPEN_NOTHING, OPEN_CLASSIC, OPEN_WINDOWS, + OPEN_CUSTOM, OPEN_BOTH, OPEN_DESKTOP, OPEN_CORTANA, @@ -3348,6 +3349,16 @@ static LRESULT CALLBACK HookProgManThread( int code, WPARAM wParam, LPARAM lPara msg->message=WM_NULL; if (control==OPEN_CLASSIC) PostMessage(g_TaskBar,g_StartMenuMsg,MSG_TOGGLE,0); + else if (control==OPEN_CUSTOM) + { + CString commandText=GetSettingString(L"WinKeyCommand"); + if (!commandText.IsEmpty()) + { + wchar_t expandedCommand[_MAX_PATH]{}; + ::ExpandEnvironmentStrings(commandText, expandedCommand, _countof(expandedCommand)); + ShellExecute(NULL,NULL,expandedCommand,NULL,NULL,SW_SHOWNORMAL); + } + } } } } @@ -3431,6 +3442,16 @@ if (!g_bTrimHooks) PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMK'); else if (control==OPEN_CORTANA) OpenCortana(); + else if (control==OPEN_CUSTOM) + { + CString commandText=GetSettingString(L"ShiftWinCommand"); + if (!commandText.IsEmpty()) + { + wchar_t expandedCommand[_MAX_PATH]{}; + ::ExpandEnvironmentStrings(commandText, expandedCommand, _countof(expandedCommand)); + ShellExecute(NULL,NULL,expandedCommand,NULL,NULL,SW_SHOWNORMAL); + } + } } else if (msg->wParam==MSG_DRAG || msg->wParam==MSG_SHIFTDRAG) { @@ -3590,12 +3611,22 @@ if (!g_bTrimHooks) // left or middle click on start button FindWindowsMenu(); const wchar_t *name; + const wchar_t *command; if (bMiddle) + { name=L"MiddleClick"; + command=L"MiddleClickCommand"; + } else if (GetKeyState(VK_SHIFT)<0) + { name=L"ShiftClick"; + command=L"ShiftClickCommand"; + } else + { name=L"MouseClick"; + command=L"MouseClickCommand"; + } int control=GetSettingInt(name); if (control==OPEN_BOTH && GetWinVersion()>=WIN_VER_WIN10) @@ -3611,6 +3642,16 @@ if (!g_bTrimHooks) PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMM'); else if (control==OPEN_CORTANA) OpenCortana(); + else if (control==OPEN_CUSTOM) + { + CString commandText=GetSettingString(command); + if (!commandText.IsEmpty()) + { + wchar_t expandedCommand[_MAX_PATH]{}; + ::ExpandEnvironmentStrings(commandText, expandedCommand, _countof(expandedCommand)); + ShellExecute(NULL,NULL,expandedCommand,NULL,NULL,SW_SHOWNORMAL); + } + } msg->message=WM_NULL; } } @@ -3751,6 +3792,16 @@ if (!g_bTrimHooks) FindWindowsMenu(); PostMessage(g_ProgWin,WM_SYSCOMMAND,SC_TASKLIST,'WSMM'); } + else if (control==OPEN_CUSTOM) + { + CString commandText=GetSettingString(L"HoverCommand"); + if (!commandText.IsEmpty()) + { + wchar_t expandedCommand[_MAX_PATH]{}; + ::ExpandEnvironmentStrings(commandText, expandedCommand, _countof(expandedCommand)); + ShellExecute(NULL,NULL,expandedCommand,NULL,NULL,SW_SHOWNORMAL); + } + } } } taskBar->bTimer=false; diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc index c857c0e20..bb4c5727e 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc @@ -1307,6 +1307,10 @@ BEGIN IDS_NEW_SEARCH_HINT_TIP "The text to replace the search hint with. Empty text is a valid option" IDS_MORE_RESULTS "Enable ""See more results"" option" IDS_MORE_RESULTS_TIP "When this is checked, the search results will include an option to do a more advanced search" + IDS_OPEN_CMD "Custom command" + IDS_OPEN_CMD_TIP "The action will run a user-defined command" + IDS_OPEN_CMD_TEXT "Command to run" + IDS_OPEN_CMD_TEXT_TIP "Enter the command to run when you use this control" END #endif // English (U.S.) resources diff --git a/Src/StartMenu/StartMenuDLL/resource.h b/Src/StartMenu/StartMenuDLL/resource.h index daeabf246..be605837f 100644 --- a/Src/StartMenu/StartMenuDLL/resource.h +++ b/Src/StartMenu/StartMenuDLL/resource.h @@ -770,6 +770,10 @@ #define IDS_NEW_SEARCH_HINT_TIP 3673 #define IDS_MORE_RESULTS 3674 #define IDS_MORE_RESULTS_TIP 3675 +#define IDS_OPEN_CMD 3676 +#define IDS_OPEN_CMD_TIP 3677 +#define IDS_OPEN_CMD_TEXT 3678 +#define IDS_OPEN_CMD_TEXT_TIP 3679 #define IDS_STRING7001 7001 #define IDS_STRING7002 7002 #define IDS_STRING7003 7003 From bb26cec0ecbdca0350e7c1474eec32954d18d14d Mon Sep 17 00:00:00 2001 From: thisismy-github <48284263+thisismy-github@users.noreply.github.com> Date: Mon, 16 Aug 2021 12:41:06 -0400 Subject: [PATCH 008/155] Added option to single-expand any Win7 style item Expands the "display as a list of drives" option from This PC to work on almost any item in the Windows 7 style. Incompatible items have a new setting called ITEM_NODRIVES which blocks the option from appearing. This PC still uses the original "list of drives" text, while other items use "list of links" instead. Sorting has been updated to account for this option by adding a property called bFolderLink which marks any folder, even if it is not explicitly expandable. --- Src/StartMenu/StartMenuDLL/CustomMenu.cpp | 10 +++++----- Src/StartMenu/StartMenuDLL/CustomMenu.h | 1 + Src/StartMenu/StartMenuDLL/DragDrop.cpp | 2 +- Src/StartMenu/StartMenuDLL/MenuContainer.cpp | 7 ++++--- Src/StartMenu/StartMenuDLL/MenuContainer.h | 16 +++++++++------- Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 16 ++++++++++++---- Src/StartMenu/StartMenuDLL/StartMenuDLL.rc | 2 ++ Src/StartMenu/StartMenuDLL/resource.h | 2 ++ 8 files changed, 36 insertions(+), 20 deletions(-) diff --git a/Src/StartMenu/StartMenuDLL/CustomMenu.cpp b/Src/StartMenu/StartMenuDLL/CustomMenu.cpp index 8d8785e38..574669c47 100644 --- a/Src/StartMenu/StartMenuDLL/CustomMenu.cpp +++ b/Src/StartMenu/StartMenuDLL/CustomMenu.cpp @@ -95,13 +95,13 @@ CStdCommand7 g_StdCommands7[]={ {L"user_videos",0,NULL,L"$Menu.UserVideosTip",NULL,&FOLDERID_Videos}, {L"control_panel",0,L"$Menu.ControlPanel",L"$Menu.ControlPanelTip",NULL,&FOLDERID_ControlPanelFolder,NULL,StdMenuItem::MENU_TRACK}, {L"pc_settings",IDS_PCSETTINGS,L"$Menu.PCSettings",L"",L"%windir%\\ImmersiveControlPanel\\SystemSettings.exe,10",NULL,NULL,StdMenuItem::MENU_TRACK,CStdCommand7::ITEM_SINGLE}, - {L"network_connections",0,NULL,L"$Menu.NetworkTip",NULL,&FOLDERID_ConnectionsFolder}, + {L"network_connections",0,NULL,L"$Menu.NetworkTip",NULL,&FOLDERID_ConnectionsFolder,NULL,0,CStdCommand7::ITEM_NODRIVES}, {L"network",0,NULL,NULL,NULL,&FOLDERID_NetworkFolder,NULL,0,CStdCommand7::ITEM_SINGLE}, - {L"printers",0,NULL,L"$Menu.PrintersTip",NULL,&FOLDERID_PrintersFolder}, + {L"printers",0,NULL,L"$Menu.PrintersTip",NULL,&FOLDERID_PrintersFolder,NULL,0,CStdCommand7::ITEM_NODRIVES}, {L"fonts",0,NULL,NULL,NULL,&FOLDERID_Fonts}, {L"desktop",0,NULL,NULL,NULL,&FOLDERID_Desktop}, - {L"admin",0,NULL,L"$Menu.AdminToolsTip",L"imageres.dll,114",&FOLDERID_CommonAdminTools,NULL,StdMenuItem::MENU_TRACK}, - {L"startup",0,NULL,NULL,NULL,&FOLDERID_Startup,NULL,StdMenuItem::MENU_TRACK}, + {L"admin",0,NULL,L"$Menu.AdminToolsTip",L"imageres.dll,114",&FOLDERID_CommonAdminTools,NULL,StdMenuItem::MENU_TRACK,CStdCommand7::ITEM_NODRIVES}, + {L"startup",0,NULL,NULL,NULL,&FOLDERID_Startup,NULL,StdMenuItem::MENU_TRACK,CStdCommand7::ITEM_NODRIVES}, {L"downloads",0,NULL,L"$Menu.DownloadTip",NULL,&FOLDERID_Downloads}, {L"games",0,NULL,L"$Menu.GamesTip",NULL,&FOLDERID_Games,NULL,StdMenuItem::MENU_TRACK}, {L"links",0,NULL,NULL,NULL,&FOLDERID_Links}, @@ -112,7 +112,7 @@ CStdCommand7 g_StdCommands7[]={ {L"lib_videos",IDS_LIB_VIDEOS_ITEM,NULL,L"$Menu.VideosLibTip",NULL,&FOLDERID_VideosLibrary}, {L"lib_tv",IDS_LIB_TV_ITEM,NULL,L"$Menu.RecordingsLibTip",NULL,&FOLDERID_RecordedTVLibrary}, {L"homegroup",0,NULL,L"$Menu.HomegroupTip",NULL,&FOLDERID_HomeGroup,NULL,0,CStdCommand7::ITEM_SINGLE}, - {L"devices",0,NULL,NULL,NULL,NULL,L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{A8A91A66-3A7D-4424-8D24-04E180695C7A}"}, + {L"devices",0,NULL,NULL,NULL,NULL,L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{A8A91A66-3A7D-4424-8D24-04E180695C7A}",0,CStdCommand7::ITEM_NODRIVES}, {L"defaults",0,NULL,NULL,NULL,NULL,L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{17CD9488-1228-4B2F-88CE-4298E93E0966}",0,CStdCommand7::ITEM_SINGLE}, {L"apps",IDS_METRO_APPS,L"$Menu.Apps",NULL,L",2",NULL,NULL,StdMenuItem::MENU_TRACK,CStdCommand7::ITEM_FOLDER}, diff --git a/Src/StartMenu/StartMenuDLL/CustomMenu.h b/Src/StartMenu/StartMenuDLL/CustomMenu.h index f2cec3f44..8ecc02df4 100644 --- a/Src/StartMenu/StartMenuDLL/CustomMenu.h +++ b/Src/StartMenu/StartMenuDLL/CustomMenu.h @@ -15,6 +15,7 @@ struct CStdCommand7 ITEM_SINGLE=1, // this item never has sub-menu ITEM_FOLDER=2, // this item always has sub-menu ITEM_COMPUTER=4, // this item can be expanded only one level + ITEM_NODRIVES=8, // this item can never be expanded only one level }; const wchar_t *command; int nameID; diff --git a/Src/StartMenu/StartMenuDLL/DragDrop.cpp b/Src/StartMenu/StartMenuDLL/DragDrop.cpp index 7b3262db8..b59865eea 100644 --- a/Src/StartMenu/StartMenuDLL/DragDrop.cpp +++ b/Src/StartMenu/StartMenuDLL/DragDrop.cpp @@ -903,7 +903,7 @@ HRESULT STDMETHODCALLTYPE CMenuContainer::Drop( IDataObject *pDataObj, DWORD grf else if (i if (bLibrary) flags&=~SFGAO_STREAM; item.bLink=(flags&SFGAO_LINK)!=0; - item.bFolder=(!(options&CONTAINER_CONTROLPANEL) && !(options&CONTAINER_NOSUBFOLDERS) && (flags&SFGAO_FOLDER) && (!(flags&(SFGAO_STREAM|SFGAO_LINK)) || (s_bExpandLinks && item.bLink))); + item.bFolderLink=(flags&SFGAO_FOLDER && (!(flags&(SFGAO_STREAM|SFGAO_LINK)) || (s_bExpandLinks && item.bLink))); + item.bFolder=(!(options&CONTAINER_CONTROLPANEL) && !(options&CONTAINER_NOSUBFOLDERS) && item.bFolderLink); { CItemManager::RWLock lock(&g_ItemManager,false,CItemManager::RWLOCK_ITEMS); if (item.pItemInfo->IsMetroLink()) @@ -2505,9 +2506,9 @@ void CMenuContainer::InitItems( void ) m_Items.resize(MAX_MENU_ITEMS); } - if (m_Options&CONTAINER_CONTROLPANEL) + if (m_Options&CONTAINER_CONTROLPANEL && !(m_Options&CONTAINER_NOSUBFOLDERS)) { - // expand Administrative Tools. must be done after the sorting because we don't want the folder to jump to the top + // expand Administrative Tools when displaying as a menu. must be done after the sorting because we don't want the folder to jump to the top unsigned int AdminToolsHash=CalcFNVHash(L"::{D20EA4E1-3957-11D2-A40B-0C5020524153}"); for (std::vector::iterator it=m_Items.begin();it!=m_Items.end();++it) if (it->nameHash==AdminToolsHash) diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.h b/Src/StartMenu/StartMenuDLL/MenuContainer.h index 84e36931c..d98210934 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.h +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.h @@ -453,7 +453,7 @@ class CMenuContainer: public IDropTarget, public IFrameworkInputPaneHandler, pub drawType=MenuSkin::COLUMN1_ITEM; column=row=0; memset(&itemRect,0,sizeof(itemRect)); - bFolder=bLink=bPrograms=bAlignBottom=bBreak=bInline=bInlineFirst=bInlineLast=bSplit=bHasJumpList=bMetroLink=bMetroApp=bBlankSeparator=bNew=bStartScreen=bCustomAccelerator=false; + bFolder=bLink=bFolderLink=bPrograms=bAlignBottom=bBreak=bInline=bInlineFirst=bInlineLast=bSplit=bHasJumpList=bMetroLink=bMetroApp=bBlankSeparator=bNew=bStartScreen=bCustomAccelerator=false; priority=0; pItem1=pItem2=NULL; mfuHash=0; @@ -477,6 +477,7 @@ class CMenuContainer: public IDropTarget, public IFrameworkInputPaneHandler, pub RECT itemRect; bool bFolder:1; // this is a folder - draw arrow bool bLink:1; // this is a link (if a link to a folder is expanded it is always single-column) + bool bFolderLink:1; // this is a folder that is not explicitly expandable - used for sorting the list-of-links style bool bPrograms:1; // this item is part of the Start Menu folder hierarchy bool bAlignBottom:1; // two-column menu: this item is aligned to the bottom bool bBreak:1; // two-column menu: this item starts the second column @@ -512,8 +513,8 @@ class CMenuContainer: public IDropTarget, public IFrameworkInputPaneHandler, pub if (priority>item.priority) return false; if (rowitem.row) return false; - if ((bFolder && !bHasJumpList) && !(item.bFolder && !item.bHasJumpList)) return true; - if (!(bFolder && !bHasJumpList) && (item.bFolder && !item.bHasJumpList)) return false; + if (((bFolder || bFolderLink) && !bHasJumpList) && !((item.bFolder || item.bFolderLink) && !item.bHasJumpList)) return true; + if (!((bFolder || bFolderLink) && !bHasJumpList) && ((item.bFolder || item.bFolderLink) && !item.bHasJumpList)) return false; if (drive && !item.drive) return true; if (!drive && item.drive) return false; if (drive && item.drive) return drivex.priority) return false; - if ((bFolder && !bHasJumpList) && !(x.bFolder && !x.bHasJumpList)) return true; - if (!(bFolder && !bHasJumpList) && (x.bFolder && !x.bHasJumpList)) return false; + if (((bFolder || bFolderLink) && !bHasJumpList) && !((x.bFolder || x.bFolderLink) && !x.bHasJumpList)) return true; + if (!((bFolder || bFolderLink) && !bHasJumpList) && ((x.bFolder || x.bFolderLink) && !x.bHasJumpList)) return false; if (drive && !x.drive) return true; if (!drive && x.drive) return false; if (drive && x.drive) return drive Date: Thu, 19 Aug 2021 14:21:11 -0400 Subject: [PATCH 009/155] Added option to open folders to their true path Adds a new function called GetFakeFolder which attempts to find and get the target.lnk file from a fake folder (what Open-Shell uses to pin folders). If detected, InvokeCommand is swapped for a ShellExecute call to the target shortcut. Fixes #555, #653, and by extension, #691. --- Src/Lib/FileHelper.cpp | 14 ++++++++++ Src/Lib/FileHelper.h | 1 + Src/StartMenu/StartMenuDLL/MenuCommands.cpp | 31 +++++++++++++++++---- Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 1 + Src/StartMenu/StartMenuDLL/StartMenuDLL.rc | 6 ++++ Src/StartMenu/StartMenuDLL/resource.h | 2 ++ 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/Src/Lib/FileHelper.cpp b/Src/Lib/FileHelper.cpp index 2d928f849..7d6664edb 100644 --- a/Src/Lib/FileHelper.cpp +++ b/Src/Lib/FileHelper.cpp @@ -60,3 +60,17 @@ bool IsFakeFolder( const wchar_t *fname ) } return false; } + +bool GetFakeFolder( wchar_t *dst, int len, const wchar_t *src ) +{ + Sprintf(dst,len,L"%s\\target.lnk",src); + if (GetFileAttributes(dst)!=INVALID_FILE_ATTRIBUTES) + { + wchar_t path[_MAX_PATH]; + Sprintf(path,_countof(path),L"%s\\desktop.ini",src); + DWORD attrib=GetFileAttributes(path); + if (attrib!=INVALID_FILE_ATTRIBUTES && (attrib&FILE_ATTRIBUTE_SYSTEM)) + return true; + } + return false; +} diff --git a/Src/Lib/FileHelper.h b/Src/Lib/FileHelper.h index 4d33ffc6a..2a5b20bbd 100644 --- a/Src/Lib/FileHelper.h +++ b/Src/Lib/FileHelper.h @@ -7,3 +7,4 @@ bool CreateFakeFolder( const wchar_t *source, const wchar_t *fname ); void DeleteFakeFolder( const wchar_t *fname ); bool IsFakeFolder( const wchar_t *fname ); +bool GetFakeFolder( wchar_t *dst, int len, const wchar_t *src ); diff --git a/Src/StartMenu/StartMenuDLL/MenuCommands.cpp b/Src/StartMenu/StartMenuDLL/MenuCommands.cpp index 2f6acd026..3f949f27b 100644 --- a/Src/StartMenu/StartMenuDLL/MenuCommands.cpp +++ b/Src/StartMenu/StartMenuDLL/MenuCommands.cpp @@ -11,6 +11,7 @@ #include "Settings.h" #include "SettingsUI.h" #include "SettingsUIHelper.h" +#include "FileHelper.h" #include "Translations.h" #include "LogManager.h" #include "FNVHash.h" @@ -2782,12 +2783,19 @@ void CMenuContainer::ActivateItem( int index, TActivateType type, const POINT *p info.lpVerb=MAKEINTRESOURCEA(res-verbOffset); info.lpVerbW=MAKEINTRESOURCEW(res-verbOffset); info.nShow=SW_SHOWNORMAL; + bool bOpenTruePath=false; + wchar_t targetlnkPath[_MAX_PATH]; // path to target.lnk in a fake folder wchar_t dir[_MAX_PATH]; if (SHGetPathFromIDList(pItemPidl1,dir)) { - PathRemoveFileSpec(dir); - if (GetFileAttributes(dir)!=INVALID_FILE_ATTRIBUTES) - info.lpDirectoryW=dir; + if (_stricmp(command,"open")==0 && GetSettingBool(L"OpenTruePath") && GetFakeFolder(targetlnkPath,_countof(targetlnkPath),dir)) + bOpenTruePath=true; + else + { + PathRemoveFileSpec(dir); + if (GetFileAttributes(dir)!=INVALID_FILE_ATTRIBUTES) + info.lpDirectoryW=dir; + } } if (pPt) { @@ -2818,9 +2826,20 @@ void CMenuContainer::ActivateItem( int index, TActivateType type, const POINT *p ::SetForegroundWindow(g_OwnerWindow); ::SetWindowPos(g_OwnerWindow,HWND_TOPMOST,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,0); LOG_MENU(LOG_EXECUTE,L"Invoke command, ptr=%p, command='%S'",this,command); - HRESULT hr=pInvokeMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info); - LOG_MENU(LOG_EXECUTE,L"Invoke command, ptr=%p, res=%d",this,hr); - if (type==ACTIVATE_EXECUTE && SUCCEEDED(hr)) + bool executeSuccess; + if (bOpenTruePath) // we are trying to open a fake folder, directly open target.lnk instead + { + HINSTANCE hinst=ShellExecute(NULL,NULL,targetlnkPath,NULL,NULL,SW_SHOWNORMAL); + LOG_MENU(LOG_EXECUTE,L"Invoke command, ptr=%p, res=%d",this,hinst); + executeSuccess=static_cast(reinterpret_cast(hinst))>=32; + } + else + { + HRESULT hr=pInvokeMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info); + LOG_MENU(LOG_EXECUTE,L"Invoke command, ptr=%p, res=%d",this,hr); + executeSuccess=SUCCEEDED(hr); + } + if (type==ACTIVATE_EXECUTE && executeSuccess) { if (bTrackRecent) { diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index 2473a36d5..98f563fac 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -4349,6 +4349,7 @@ CSetting g_Settings[]={ {L"SearchFilesCommand",CSetting::TYPE_STRING,IDS_SEARCH_COMMAND,IDS_SEARCH_COMMAND_TIP,L"search-ms:",CSetting::FLAG_MENU_CLASSIC_BOTH}, {L"ExpandFolderLinks",CSetting::TYPE_BOOL,IDS_EXPAND_LINKS,IDS_EXPAND_LINKS_TIP,1}, {L"SingleClickFolders",CSetting::TYPE_BOOL,IDS_NO_DBLCLICK,IDS_NO_DBLCLICK_TIP,0}, + {L"OpenTruePath",CSetting::TYPE_BOOL,IDS_OPEN_TRUE_PATH,IDS_OPEN_TRUE_PATH_TIP,1}, {L"EnableTouch",CSetting::TYPE_BOOL,IDS_ENABLE_TOUCH,IDS_ENABLE_TOUCH_TIP,1}, {L"EnableAccessibility",CSetting::TYPE_BOOL,IDS_ACCESSIBILITY,IDS_ACCESSIBILITY_TIP,1}, {L"ShowNextToTaskbar",CSetting::TYPE_BOOL,IDS_NEXTTASKBAR,IDS_NEXTTASKBAR_TIP,0}, diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc index 52fb7259c..57feae1a6 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc @@ -1315,6 +1315,12 @@ BEGIN IDS_ITEM_LINKS_TIP "This item will appear as a sub-menu showing only its top-level contents" END +STRINGTABLE +BEGIN + IDS_OPEN_TRUE_PATH "Open pinned folders to their true path" + IDS_OPEN_TRUE_PATH_TIP "When this is checked, pinned folders will open to their true path instead of the path to their shortcut in the Pinned Programs folder" +END + #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/Src/StartMenu/StartMenuDLL/resource.h b/Src/StartMenu/StartMenuDLL/resource.h index 8cdf1b0ec..e5fa09934 100644 --- a/Src/StartMenu/StartMenuDLL/resource.h +++ b/Src/StartMenu/StartMenuDLL/resource.h @@ -776,6 +776,8 @@ #define IDS_OPEN_CMD_TEXT_TIP 3679 #define IDS_ITEM_LINKS 3680 #define IDS_ITEM_LINKS_TIP 3681 +#define IDS_OPEN_TRUE_PATH 3682 +#define IDS_OPEN_TRUE_PATH_TIP 3683 #define IDS_STRING7001 7001 #define IDS_STRING7002 7002 #define IDS_STRING7003 7003 From 8031739110555868e596aa9118f25d9b11287caa Mon Sep 17 00:00:00 2001 From: thisismy-github <48284263+thisismy-github@users.noreply.github.com> Date: Thu, 19 Aug 2021 18:52:06 -0400 Subject: [PATCH 010/155] Added option to customize Pinned folder location Items can be pinned to directories that require administative privileges (such as Open-Shell's default installation directory), so long as users take ownership of the pinned folder. Also adds a command to Open-Shell's context menu that opens the current pinned folder. Adds general support for directory-based settings by creating a new setting type called TYPE_DIRECTORY which uses a new bool added to BrowseLinkHelper, called bFoldersOnly. START_MENU_PINNED_ROOT has been removed, and all instances of both it and BrowseLinkHelper have been adjusted accordingly. To create your own directory-based settings, use CSetting::TYPE_DIRECTORY. Empty directory paths are reset to their default value as they can cause unexpected behavior. --- Src/ClassicExplorer/SettingsUI.cpp | 2 +- Src/Lib/Settings.cpp | 10 +-- Src/Lib/Settings.h | 1 + Src/Lib/SettingsUIHelper.cpp | 71 +++++++++++++++---- Src/Lib/SettingsUIHelper.h | 2 +- Src/StartMenu/StartMenuDLL/ItemManager.cpp | 5 +- Src/StartMenu/StartMenuDLL/ItemManager.h | 1 - Src/StartMenu/StartMenuDLL/MenuContainer.cpp | 6 +- Src/StartMenu/StartMenuDLL/SearchManager.cpp | 3 +- Src/StartMenu/StartMenuDLL/SettingsUI.cpp | 5 +- Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp | 13 ++++ Src/StartMenu/StartMenuDLL/StartMenuDLL.rc | 4 +- Src/StartMenu/StartMenuDLL/resource.h | 2 + .../StartMenuHelper/StartMenuExt.cpp | 2 +- Src/StartMenu/StartMenuHelper/dllmain.cpp | 1 + 15 files changed, 99 insertions(+), 29 deletions(-) diff --git a/Src/ClassicExplorer/SettingsUI.cpp b/Src/ClassicExplorer/SettingsUI.cpp index f70b77a5e..8be0eedad 100644 --- a/Src/ClassicExplorer/SettingsUI.cpp +++ b/Src/ClassicExplorer/SettingsUI.cpp @@ -380,7 +380,7 @@ LRESULT CEditToolbarDlg::OnBrowseLink( WORD wNotifyCode, WORD wID, HWND hWndCtl, { wchar_t text[_MAX_PATH]; GetDlgItemText(IDC_COMBOLINK,text,_countof(text)); - if (BrowseLinkHelper(m_hWnd,text)) + if (BrowseLinkHelper(m_hWnd,text,false)) { SetDlgItemText(IDC_COMBOLINK,text); SendMessage(WM_COMMAND,MAKEWPARAM(IDC_COMBOLINK,CBN_KILLFOCUS)); diff --git a/Src/Lib/Settings.cpp b/Src/Lib/Settings.cpp index fb312fc8b..00903e87b 100644 --- a/Src/Lib/Settings.cpp +++ b/Src/Lib/Settings.cpp @@ -125,7 +125,7 @@ bool CSetting::IsEnabled( void ) const if (operation=='>' && pSetting->GetValue().intVal<=val) return false; } - if ((pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG) && pSetting->GetValue().vt==VT_BSTR) + if ((pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG || pSetting->type==CSetting::TYPE_DIRECTORY) && pSetting->GetValue().vt==VT_BSTR) { if (operation=='~' && *pSetting->GetValue().bstrVal==0) return false; @@ -202,7 +202,7 @@ bool CSetting::ReadValue( CRegKey ®Key, const wchar_t *valName ) } // string - if (type>=CSetting::TYPE_STRING && type=CSetting::TYPE_STRING && type!=CSetting::TYPE_MULTISTRING) { ULONG len; if (regKey.QueryStringValue(valName,NULL,&len)==ERROR_SUCCESS) @@ -2221,7 +2221,7 @@ bool GetSettingBool( const CSetting &setting ) CString GetSettingString( const CSetting &setting ) { - Assert(setting.type==CSetting::TYPE_STRING); + Assert(setting.type==CSetting::TYPE_STRING || setting.type==CSetting::TYPE_DIRECTORY); if (setting.value.vt!=VT_BSTR) return CString(); return setting.value.bstrVal; @@ -2722,7 +2722,7 @@ bool SaveAdmx( TSettingsComponent component, const char *admxFile, const char *a { fprintf_s(fAdmx,"\t\t\t\t\r\n",pSetting->name); } - else if (pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_ICON || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG || pSetting->type==CSetting::TYPE_SOUND || pSetting->type==CSetting::TYPE_FONT) + else if (pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_ICON || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG || pSetting->type==CSetting::TYPE_SOUND || pSetting->type==CSetting::TYPE_FONT || pSetting->type==CSetting::TYPE_DIRECTORY) { fprintf_s(fAdmx,"\t\t\t\t\r\n",pSetting->name); } @@ -2782,7 +2782,7 @@ bool SaveAdmx( TSettingsComponent component, const char *admxFile, const char *a { fprintf_s(fAdml,"\t\t\t\t%s\r\n",(const char*)name); } - else if (pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_ICON || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG || pSetting->type==CSetting::TYPE_SOUND || pSetting->type==CSetting::TYPE_FONT) + else if (pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_ICON || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG || pSetting->type==CSetting::TYPE_SOUND || pSetting->type==CSetting::TYPE_FONT || pSetting->type==CSetting::TYPE_DIRECTORY) { fprintf_s(fAdml,"\t\t\t\t\r\n",(const char*)name); } diff --git a/Src/Lib/Settings.h b/Src/Lib/Settings.h index 0306a85d2..fd945e256 100644 --- a/Src/Lib/Settings.h +++ b/Src/Lib/Settings.h @@ -32,6 +32,7 @@ struct CSetting TYPE_SOUND, TYPE_FONT, TYPE_MULTISTRING, + TYPE_DIRECTORY, }; enum diff --git a/Src/Lib/SettingsUIHelper.cpp b/Src/Lib/SettingsUIHelper.cpp index 0c3221223..5c22f587d 100644 --- a/Src/Lib/SettingsUIHelper.cpp +++ b/Src/Lib/SettingsUIHelper.cpp @@ -1216,7 +1216,7 @@ bool BrowseCommandHelper( HWND parent, wchar_t *text ) return false; } -bool BrowseLinkHelper( HWND parent, wchar_t *text ) +bool BrowseLinkHelper( HWND parent, wchar_t *text, bool bFoldersOnly ) { DoEnvironmentSubst(text,_MAX_PATH); @@ -1227,16 +1227,22 @@ bool BrowseLinkHelper( HWND parent, wchar_t *text ) if (!pCustomize) return false; - pDialog->SetTitle(LoadStringEx(IDS_PICK_LINK_TITLE)); - pDialog->SetOkButtonLabel(LoadStringEx(IDS_PICK_LINK_FILE)); - wchar_t button[256]; - Sprintf(button,_countof(button),L" %s ",LoadStringEx(IDS_PICK_LINK_FOLDER)); - pCustomize->AddPushButton(101,button); + pDialog->SetTitle(LoadStringEx(bFoldersOnly?IDS_PICK_LINK_FOLDER:IDS_PICK_LINK_TITLE)); + if (!bFoldersOnly) // add separate buttons for selecting files/folders to the dialog + { + pDialog->SetOkButtonLabel(LoadStringEx(IDS_PICK_LINK_FILE)); + wchar_t button[256]; + Sprintf(button,_countof(button),L" %s ",LoadStringEx(IDS_PICK_LINK_FOLDER)); + pCustomize->AddPushButton(101,button); + } CBrowseLinkEvents events; DWORD cookie; pDialog->Advise(&events,&cookie); - pDialog->SetOptions(FOS_ALLNONSTORAGEITEMS|FOS_FILEMUSTEXIST|FOS_DONTADDTORECENT|FOS_DEFAULTNOMINIMODE|FOS_NODEREFERENCELINKS); + if (bFoldersOnly) // set FOS_PICKFOLDERS option to use dialog in folder-only mode + pDialog->SetOptions(FOS_PICKFOLDERS|FOS_ALLNONSTORAGEITEMS|FOS_DONTADDTORECENT|FOS_DEFAULTNOMINIMODE); + else + pDialog->SetOptions(FOS_ALLNONSTORAGEITEMS|FOS_FILEMUSTEXIST|FOS_DONTADDTORECENT|FOS_DEFAULTNOMINIMODE|FOS_NODEREFERENCELINKS); { const wchar_t *c=wcschr(text,'|'); if (c) @@ -2274,6 +2280,7 @@ class CTreeSettingsDlg: public CResizeableDlg EDIT_HOTKEY_ANY, EDIT_COLOR, EDIT_FONT, + EDIT_DIRECTORY, }; BEGIN_MSG_MAP( CTreeSettingsDlg ) @@ -2717,6 +2724,29 @@ LRESULT CTreeSettingsDlg::OnBrowse( WORD wNotifyCode, WORD wID, HWND hWndCtl, BO m_EditBox.SetFocus(); m_bIgnoreFocus=false; } + else if (m_EditMode==EDIT_DIRECTORY) + { + m_bIgnoreFocus=true; + CString str; + m_EditBox.GetWindowText(str); + str.TrimLeft(); str.TrimRight(); + wchar_t text[1024]; + DWORD dwAttrs=GetFileAttributes(str); // ensure directory exists before passing it to dialog + if (dwAttrs!=INVALID_FILE_ATTRIBUTES && dwAttrs&FILE_ATTRIBUTE_DIRECTORY) + { + Strcpy(text,_countof(text),str); + DoEnvironmentSubst(text,_countof(text)); + } + else + text[0]=0; + Strcpy(text,_countof(text),str); + DoEnvironmentSubst(text,_countof(text)); + if (BrowseLinkHelper(m_hWnd,text,true)) + m_EditBox.SetWindowText(text); + SendMessage(WM_NEXTDLGCTL,(LPARAM)m_EditBox.m_hWnd,TRUE); + m_EditBox.SetFocus(); + m_bIgnoreFocus=false; + } return 0; } @@ -3052,6 +3082,20 @@ void CTreeSettingsDlg::ApplyEditBox( void ) pSetting->flags&=~CSetting::FLAG_DEFAULT; } } + else if (pSetting->type==CSetting::TYPE_DIRECTORY) + { + if (pSetting->value.vt!=VT_BSTR || str!=pSetting->value.bstrVal) + { + if (str.IsEmpty()) // empty directory strings cause unexpected behavior, so we reset to avoid this + pSetting->value=pSetting->defValue; + else // otherwise we are very lenient about what users can input as a path + pSetting->value=CComVariant(str); + if (pSetting->value==pSetting->defValue) + pSetting->flags|=CSetting::FLAG_DEFAULT; + else + pSetting->flags&=~CSetting::FLAG_DEFAULT; + } + } else { if (pSetting->value.vt!=VT_BSTR || str!=pSetting->value.bstrVal) @@ -3095,7 +3139,7 @@ void CTreeSettingsDlg::ItemSelected( HTREEITEM hItem, CSetting *pSetting, bool b val=valVar.intVal; Sprintf(text,_countof(text),L"%d",val); } - else if (pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_ICON || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG || pSetting->type==CSetting::TYPE_SOUND || pSetting->type==CSetting::TYPE_FONT) + else if (pSetting->type==CSetting::TYPE_STRING || pSetting->type==CSetting::TYPE_ICON || pSetting->type==CSetting::TYPE_BITMAP || pSetting->type==CSetting::TYPE_BITMAP_JPG || pSetting->type==CSetting::TYPE_SOUND || pSetting->type==CSetting::TYPE_FONT || pSetting->type==CSetting::TYPE_DIRECTORY) { if (valVar.vt==VT_BSTR) Strcpy(text,_countof(text),valVar.bstrVal); @@ -3111,8 +3155,10 @@ void CTreeSettingsDlg::ItemSelected( HTREEITEM hItem, CSetting *pSetting, bool b mode=EDIT_BITMAP_JPG; else if (pSetting->type==CSetting::TYPE_SOUND) mode=EDIT_SOUND; - else + else if (pSetting->type==CSetting::TYPE_FONT) mode=EDIT_FONT; + else + mode=EDIT_DIRECTORY; } else if (pSetting->type==CSetting::TYPE_HOTKEY || pSetting->type==CSetting::TYPE_HOTKEY_ANY) { @@ -3152,7 +3198,7 @@ void CTreeSettingsDlg::ItemSelected( HTREEITEM hItem, CSetting *pSetting, bool b m_pEditSetting=pSetting; } - if (mode==EDIT_ICON || mode==EDIT_BITMAP || mode==EDIT_BITMAP_JPG || mode==EDIT_SOUND || mode==EDIT_FONT || mode==EDIT_COLOR) + if (mode==EDIT_ICON || mode==EDIT_BITMAP || mode==EDIT_BITMAP_JPG || mode==EDIT_SOUND || mode==EDIT_FONT || mode==EDIT_COLOR || mode==EDIT_DIRECTORY) { RECT rc2=rc; int width=(rc2.bottom-rc2.top)*3/2; @@ -3210,14 +3256,15 @@ void CTreeSettingsDlg::UpdateEditPosition( void ) DeleteDC(hdc); DWORD margins=(DWORD)m_EditBox.SendMessage(EM_GETMARGINS); size.cx+=HIWORD(margins)+LOWORD(margins)+12; - if (m_EditMode==EDIT_ICON || m_EditMode==EDIT_BITMAP || m_EditMode==EDIT_BITMAP_JPG || m_EditMode==EDIT_FONT || m_EditMode==EDIT_COLOR) + // adjust size and position of edit boxes for settings that use browse/play buttons + if (m_EditMode==EDIT_ICON || m_EditMode==EDIT_BITMAP || m_EditMode==EDIT_BITMAP_JPG || m_EditMode==EDIT_FONT || m_EditMode==EDIT_COLOR || m_EditMode==EDIT_DIRECTORY) size.cx+=width; if (m_EditMode==EDIT_SOUND) size.cx+=width*2; if (size.cx pFolder; if (SUCCEEDED(SHCreateItemFromParsingName(path,NULL,IID_IShellItem,(void**)&pFolder))) diff --git a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp index 98f563fac..008a009e8 100644 --- a/Src/StartMenu/StartMenuDLL/SettingsUI.cpp +++ b/Src/StartMenu/StartMenuDLL/SettingsUI.cpp @@ -1742,7 +1742,7 @@ LRESULT CEditMenuDlg::OnBrowseLink( WORD wNotifyCode, WORD wID, HWND hWndCtl, BO { wchar_t text[_MAX_PATH]; GetDlgItemText(IDC_COMBOLINK,text,_countof(text)); - if (BrowseLinkHelper(m_hWnd,text)) + if (BrowseLinkHelper(m_hWnd,text,false)) { SetDlgItemText(IDC_COMBOLINK,text); SendMessage(WM_COMMAND,MAKEWPARAM(IDC_COMBOLINK,CBN_KILLFOCUS)); @@ -2437,7 +2437,7 @@ LRESULT CEditMenuDlg7::OnBrowseLink( WORD wNotifyCode, WORD wID, HWND hWndCtl, B { wchar_t text[_MAX_PATH]; GetDlgItemText(IDC_EDITLINK2,text,_countof(text)); - if (BrowseLinkHelper(m_hWnd,text)) + if (BrowseLinkHelper(m_hWnd,text,false)) { SetDlgItemText(IDC_EDITLINK2,text); SendMessage(WM_COMMAND,MAKEWPARAM(IDC_EDITLINK2,EN_KILLFOCUS)); @@ -4280,6 +4280,7 @@ CSetting g_Settings[]={ {L"PinnedPrograms",CSetting::TYPE_INT,IDS_PINNED_PROGRAMS,IDS_PINNED_PROGRAMS_TIP,PINNED_PROGRAMS_PINNED}, {L"FastItems",CSetting::TYPE_RADIO,IDS_FAST_ITEMS,IDS_FAST_ITEMS_TIP}, {L"PinnedItems",CSetting::TYPE_RADIO,IDS_PINNED_ITEMS,IDS_PINNED_ITEMS_TIP}, + {L"PinnedItemsPath",CSetting::TYPE_DIRECTORY,IDS_PINNED_PATH,IDS_PINNED_PATH_TIP,L"%APPDATA%\\OpenShell\\Pinned",0,L"PinnedPrograms=1",L"PinnedItems"}, {L"RecentPrograms",CSetting::TYPE_INT,IDS_RECENT_PROGRAMS,IDS_RECENT_PROGRAMS_TIP,RECENT_PROGRAMS_RECENT,CSetting::FLAG_BASIC}, {L"None",CSetting::TYPE_RADIO,IDS_NO_RECENT,IDS_NO_RECENT_TIP}, {L"Recent",CSetting::TYPE_RADIO,IDS_SHOW_RECENT,IDS_SHOW_RECENT_TIP}, diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp b/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp index feef6452d..e1aa81ab8 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.cpp @@ -3856,6 +3856,7 @@ if (!g_bTrimHooks) CMD_OPEN, CMD_OPEN_ALL, CMD_EXPLORER, + CMD_OPEN_PINNED, }; // right-click on the start button - open the context menu (Settings, Help, Exit) @@ -3876,6 +3877,8 @@ if (!g_bTrimHooks) AppendMenu(menu,MF_STRING,CMD_OPEN,FindTranslation(L"Menu.Open",L"&Open")); if (!SHRestricted(REST_NOCOMMONGROUPS)) AppendMenu(menu,MF_STRING,CMD_OPEN_ALL,FindTranslation(L"Menu.OpenAll",L"O&pen All Users")); + if (GetSettingInt(L"PinnedPrograms")==PINNED_PROGRAMS_PINNED) + AppendMenu(menu,MF_STRING,CMD_OPEN_PINNED,FindTranslation(L"Menu.OpenPinned",L"O&pen Pinned")); AppendMenu(menu,MF_SEPARATOR,0,0); } if (GetSettingBool(L"EnableSettings")) @@ -3922,6 +3925,16 @@ if (!g_bTrimHooks) if (SUCCEEDED(ShGetKnownFolderPath((res==CMD_OPEN)?FOLDERID_StartMenu:FOLDERID_CommonStartMenu,&pPath))) ShellExecute(NULL,L"open",pPath,NULL,NULL,SW_SHOWNORMAL); } + if (res==CMD_OPEN_PINNED) // open pinned folder + { + SHELLEXECUTEINFO execute={sizeof(execute)}; + CString path=GetSettingString(L"PinnedItemsPath"); + execute.lpVerb=L"open"; + execute.lpFile=path; + execute.nShow=SW_SHOWNORMAL; + execute.fMask=SEE_MASK_DOENVSUBST; + ShellExecuteEx(&execute); + } if (res==CMD_EXPLORER) { CString path=GetSettingString(L"ExplorerPath"); diff --git a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc index 57feae1a6..6ca0538b4 100644 --- a/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc +++ b/Src/StartMenu/StartMenuDLL/StartMenuDLL.rc @@ -1044,7 +1044,7 @@ BEGIN IDS_FOLDERS_FIRST "Show folders first" IDS_FOLDERS_FIRST_TIP "When this is checked, the All Programs tree will show the folders first and the programs last" IDS_PINNED_PROGRAMS "Pinned Programs folder" - IDS_PINNED_PROGRAMS_TIP "Select the location to store the pinned programs" + IDS_PINNED_PROGRAMS_TIP "Select the location to store pinned programs. After updating this setting, close this window in order to pin items through the context menu again" IDS_FAST_ITEMS "Use Start Menu folder" END @@ -1319,6 +1319,8 @@ STRINGTABLE BEGIN IDS_OPEN_TRUE_PATH "Open pinned folders to their true path" IDS_OPEN_TRUE_PATH_TIP "When this is checked, pinned folders will open to their true path instead of the path to their shortcut in the Pinned Programs folder" + IDS_PINNED_PATH "Pinned folder path" + IDS_PINNED_PATH_TIP "The path to use as the Pinned folder. If the path does not exist, it will be created (if possible) after opening the start menu. Close this window after updating this setting to update your context menu.\n\nNote: If you do not have permissions for the selected path, you will not be able to pin items until you take ownership of the new folder" END #endif // English (U.S.) resources diff --git a/Src/StartMenu/StartMenuDLL/resource.h b/Src/StartMenu/StartMenuDLL/resource.h index e5fa09934..ea115435d 100644 --- a/Src/StartMenu/StartMenuDLL/resource.h +++ b/Src/StartMenu/StartMenuDLL/resource.h @@ -778,6 +778,8 @@ #define IDS_ITEM_LINKS_TIP 3681 #define IDS_OPEN_TRUE_PATH 3682 #define IDS_OPEN_TRUE_PATH_TIP 3683 +#define IDS_PINNED_PATH 3684 +#define IDS_PINNED_PATH_TIP 3685 #define IDS_STRING7001 7001 #define IDS_STRING7002 7002 #define IDS_STRING7003 7003 diff --git a/Src/StartMenu/StartMenuHelper/StartMenuExt.cpp b/Src/StartMenu/StartMenuHelper/StartMenuExt.cpp index 10a3b3054..5cf4aff21 100644 --- a/Src/StartMenu/StartMenuHelper/StartMenuExt.cpp +++ b/Src/StartMenu/StartMenuHelper/StartMenuExt.cpp @@ -91,7 +91,7 @@ STDMETHODIMP CStartMenuExt::Initialize( PCIDLIST_ABSOLUTE pidlFolder, IDataObjec bUsePinned=(setting==1); if (bUsePinned) { - Strcpy(m_PinFolder1,_countof(m_PinFolder1),L"%APPDATA%\\OpenShell\\Pinned\\"); + Sprintf(m_PinFolder1,_countof(m_PinFolder1),L"%s\\",GetSettingString(L"PinnedItemsPath")); DoEnvironmentSubst(m_PinFolder1,_countof(m_PinFolder1)); m_PinFolder2[0]=0; } diff --git a/Src/StartMenu/StartMenuHelper/dllmain.cpp b/Src/StartMenu/StartMenuHelper/dllmain.cpp index 10c2ced4e..795032af0 100644 --- a/Src/StartMenu/StartMenuHelper/dllmain.cpp +++ b/Src/StartMenu/StartMenuHelper/dllmain.cpp @@ -57,6 +57,7 @@ CSetting g_Settings[]={ {L"DisablePinExt",CSetting::TYPE_BOOL,0,0,0}, {L"FolderStartMenu",CSetting::TYPE_STRING,0,0,L""}, {L"FolderCommonStartMenu",CSetting::TYPE_STRING,0,0,L""}, + {L"PinnedItemsPath",CSetting::TYPE_DIRECTORY,0,0,L"%APPDATA%\\OpenShell\\Pinned"}, {L"Language",CSetting::TYPE_GROUP}, {L"Language",CSetting::TYPE_STRING,0,0,L"",CSetting::FLAG_COLD|CSetting::FLAG_SHARED}, From 64259f73e89a6fa83ee222c87bd9ed42cc11ddcc Mon Sep 17 00:00:00 2001 From: thisismy-github <48284263+thisismy-github@users.noreply.github.com> Date: Fri, 20 Aug 2021 21:16:00 -0400 Subject: [PATCH 011/155] Various single-click option fixes Fixed single-click option ignoring split arrows Fixed Apps folder being clickable --- Src/StartMenu/StartMenuDLL/MenuContainer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp index ef0a07891..bfcdedc11 100644 --- a/Src/StartMenu/StartMenuDLL/MenuContainer.cpp +++ b/Src/StartMenu/StartMenuDLL/MenuContainer.cpp @@ -6808,7 +6808,7 @@ LRESULT CMenuContainer::OnLButtonDblClick( UINT uMsg, WPARAM wParam, LPARAM lPar ClientToScreen(&pt); if (s_bWin7Style && item.id==MENU_PROGRAMS) // only single clicks for All Programs OnLButtonDown(WM_LBUTTONDOWN,wParam,lParam,bHandled); - else if (!bArrow) // ignore double-click on the split arrow + else if (!bArrow && item.id!=MENU_APPS) // ignore double-click on the split arrow and Apps folder ActivateItem(index,ACTIVATE_EXECUTE,&pt); return 0; } @@ -6832,7 +6832,7 @@ LRESULT CMenuContainer::OnLButtonUp( UINT uMsg, WPARAM wParam, LPARAM lParam, BO const MenuItem &item=m_Items[index]; POINT pt2=pt; ClientToScreen(&pt2); - if (!item.bFolder || (s_bSingleClickFolders && item.id!=MENU_PROGRAMS)) // never open All Programs link with single click + if (!item.bFolder || (s_bSingleClickFolders && item.id!=MENU_PROGRAMS && item.id!=MENU_APPS && !bArrow)) // never open All Programs, Apps folder, or jumplists with single click { if (item.jumpIndex>=0 && m_bHotArrow) { From 86447299b12fbd3d2a9cac83faca7850f4d62a29 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sun, 21 Aug 2022 14:00:12 +0200 Subject: [PATCH 012/155] AppVeyor: build only from master We want to do official builds from master only. PR builds should be not affected by this. --- appveyor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 9b62786a9..14442dfb7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,7 @@ version: 4.4.{build} +branches: + only: + - master pull_requests: do_not_increment_build_number: true skip_tags: true From 93245dc4d6d8f3ebdb46e50cbbdc65c4583835d0 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sun, 21 Aug 2022 14:01:21 +0200 Subject: [PATCH 013/155] AppVeyor: deploy build to GitHub releases page --- appveyor.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 14442dfb7..b3227bd4f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,3 +14,10 @@ only_commits: files: - Src/ - Localization/ +deploy: +- provider: GitHub + tag: v$(APPVEYOR_BUILD_VERSION) + release: $(APPVEYOR_BUILD_VERSION) + auth_token: + secure: 01CsOFRdj9KFb1hp/RlFK/F1UzGhzwGQfok6OoqcL1ipbOwRF//Phbdm7iaFVWIx + prerelease: true From 3d1fa11973cc4330eccaf05e717a9744c71105e9 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sun, 21 Aug 2022 22:20:32 +0200 Subject: [PATCH 014/155] Update README.md - Updated "release" badge to point to latest release version directly - Removed "Latest nightly build" link as nightly builds are now part of standard Releases page --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index de91f0959..874d71caa 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,10 @@ *Originally* **[Classic Shell](http://www.classicshell.net)** *by [Ivo Beltchev](https://sourceforge.net/u/ibeltchev/profile/)* -[![GitHub Release](https://img.shields.io/github/release/Open-Shell/Open-Shell-Menu.svg)](https://github.com/Open-Shell/Open-Shell-Menu/releases) [![GitHub Pre-Release](https://img.shields.io/github/release/Open-Shell/Open-Shell-Menu/all.svg)](https://github.com/Open-Shell/Open-Shell-Menu/releases) [![Build status](https://ci.appveyor.com/api/projects/status/2wj5x5qoypfjj0tr/branch/master?svg=true)](https://ci.appveyor.com/project/passionate-coder/open-shell-menu/branch/master) [![GitQ](https://gitq.com/badge.svg)](https://gitq.com/passionate-coder/Classic-Start) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/open-shell/Lobby) [![Discord](https://img.shields.io/discord/757701054782636082?color=%4E5D94&label=Discord&logo=discord&logoColor=white)](https://discord.gg/7H6arr5) +[![GitHub Release](https://img.shields.io/github/release/Open-Shell/Open-Shell-Menu.svg)](https://github.com/Open-Shell/Open-Shell-Menu/releases/latest) [![GitHub Pre-Release](https://img.shields.io/github/release/Open-Shell/Open-Shell-Menu/all.svg)](https://github.com/Open-Shell/Open-Shell-Menu/releases) [![Build status](https://ci.appveyor.com/api/projects/status/2wj5x5qoypfjj0tr/branch/master?svg=true)](https://ci.appveyor.com/project/passionate-coder/open-shell-menu/branch/master) [![GitQ](https://gitq.com/badge.svg)](https://gitq.com/passionate-coder/Classic-Start) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/open-shell/Lobby) [![Discord](https://img.shields.io/discord/757701054782636082?color=%4E5D94&label=Discord&logo=discord&logoColor=white)](https://discord.gg/7H6arr5) [Home Page](https://open-shell.github.io/Open-Shell-Menu) [Gitter Discussion room](https://gitter.im/Open-Shell) -[Latest nightly build](https://ci.appveyor.com/project/passionate-coder/open-shell-menu/branch/master/artifacts) ### Features - Classic style Start Menu for Windows 7, 8, 8.1, 10 From f01c126b3649fdfee90ba3bf6b41a0aa08966c1b Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sun, 21 Aug 2022 22:46:02 +0200 Subject: [PATCH 015/155] AppVeyor: Deploy only if build was done under official account --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index b3227bd4f..bef9420e2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,6 +18,8 @@ deploy: - provider: GitHub tag: v$(APPVEYOR_BUILD_VERSION) release: $(APPVEYOR_BUILD_VERSION) + on: + APPVEYOR_ACCOUNT_NAME: passionate-coder auth_token: secure: 01CsOFRdj9KFb1hp/RlFK/F1UzGhzwGQfok6OoqcL1ipbOwRF//Phbdm7iaFVWIx prerelease: true From 5bee5ae143585b0e5b71681aed580fac25b7fe36 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sun, 21 Aug 2022 19:24:58 +0200 Subject: [PATCH 016/155] Update JSON library to latest version (3.11.2) --- Src/Lib/json.hpp | 13861 +++++++++++++++++++++------------------------ 1 file changed, 6505 insertions(+), 7356 deletions(-) diff --git a/Src/Lib/json.hpp b/Src/Lib/json.hpp index a70aaf8cb..4d1a37ad7 100644 --- a/Src/Lib/json.hpp +++ b/Src/Lib/json.hpp @@ -1,44 +1,30 @@ -/* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 3.9.1 -|_____|_____|_____|_|___| https://github.com/nlohmann/json - -Licensed under the MIT License . -SPDX-License-Identifier: MIT -Copyright (c) 2013-2019 Niels Lohmann . - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ #ifndef INCLUDE_NLOHMANN_JSON_HPP_ #define INCLUDE_NLOHMANN_JSON_HPP_ -#define NLOHMANN_JSON_VERSION_MAJOR 3 -#define NLOHMANN_JSON_VERSION_MINOR 9 -#define NLOHMANN_JSON_VERSION_PATCH 1 - #include // all_of, find, for_each #include // nullptr_t, ptrdiff_t, size_t #include // hash, less #include // initializer_list -#include // istream, ostream +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO #include // random_access_iterator_tag #include // unique_ptr #include // accumulate @@ -47,11 +33,129 @@ SOFTWARE. #include // vector // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // transform @@ -67,63 +171,169 @@ SOFTWARE. #include // valarray // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include // nullptr_t #include // exception #include // runtime_error #include // to_string +#include // vector -// #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include // array #include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + -namespace nlohmann +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void { + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { -/// struct to capture the start position of the current token -struct position_t + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch { - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; }; -} // namespace detail -} // namespace nlohmann +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; -// #include +template class Op, class... Args> +using is_detected = typename detector::value_t; +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END -#include // pair // #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + /* Hedley - https://nemequ.github.io/hedley * Created by Evan Nemerson - * - * To the extent possible under law, the author(s) have dedicated all - * copyright and related and neighboring rights to this software to - * the public domain worldwide. This software is distributed without - * any warranty. - * - * For details, see . - * SPDX-License-Identifier: CC0-1.0 */ -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 13) +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) #if defined(JSON_HEDLEY_VERSION) #undef JSON_HEDLEY_VERSION #endif -#define JSON_HEDLEY_VERSION 13 +#define JSON_HEDLEY_VERSION 15 #if defined(JSON_HEDLEY_STRINGIFY_EX) #undef JSON_HEDLEY_STRINGIFY_EX @@ -196,18 +406,18 @@ struct position_t #if defined(JSON_HEDLEY_MSVC_VERSION) #undef JSON_HEDLEY_MSVC_VERSION #endif -#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) -#elif defined(_MSC_FULL_VER) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) -#elif defined(_MSC_VER) +#elif defined(_MSC_VER) && !defined(__ICL) #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) #endif #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) #undef JSON_HEDLEY_MSVC_VERSION_CHECK #endif -#if !defined(_MSC_VER) +#if !defined(JSON_HEDLEY_MSVC_VERSION) #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) #elif defined(_MSC_VER) && (_MSC_VER >= 1400) #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) @@ -220,9 +430,9 @@ struct position_t #if defined(JSON_HEDLEY_INTEL_VERSION) #undef JSON_HEDLEY_INTEL_VERSION #endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) -#elif defined(__INTEL_COMPILER) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) #endif @@ -235,6 +445,22 @@ struct position_t #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) #endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + #if defined(JSON_HEDLEY_PGI_VERSION) #undef JSON_HEDLEY_PGI_VERSION #endif @@ -474,7 +700,7 @@ struct position_t #if __VER__ > 1000 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) #else - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0) + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) #endif #endif @@ -551,6 +777,22 @@ struct position_t #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) #endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + #if defined(JSON_HEDLEY_GCC_VERSION) #undef JSON_HEDLEY_GCC_VERSION #endif @@ -560,6 +802,7 @@ struct position_t !defined(JSON_HEDLEY_INTEL_VERSION) && \ !defined(JSON_HEDLEY_PGI_VERSION) && \ !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ !defined(JSON_HEDLEY_TI_VERSION) && \ !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ @@ -567,7 +810,8 @@ struct position_t !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ - !defined(__COMPCERT__) + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION #endif @@ -583,17 +827,21 @@ struct position_t #if defined(JSON_HEDLEY_HAS_ATTRIBUTE) #undef JSON_HEDLEY_HAS_ATTRIBUTE #endif -#if defined(__has_attribute) - #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) #else - #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) #endif #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE #endif #if defined(__has_attribute) - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) #else #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) #endif @@ -602,7 +850,7 @@ struct position_t #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE #endif #if defined(__has_attribute) - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) #else #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif @@ -787,6 +1035,72 @@ struct position_t #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) #endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) @@ -795,12 +1109,22 @@ struct position_t #if defined(__cplusplus) # if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") # if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ xpr \ JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif # else # define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ @@ -865,7 +1189,7 @@ struct position_t # define JSON_HEDLEY_CPP_CAST(T, expr) \ JSON_HEDLEY_DIAGNOSTIC_PUSH \ _Pragma("diag_suppress=Pe137") \ - JSON_HEDLEY_DIAGNOSTIC_POP \ + JSON_HEDLEY_DIAGNOSTIC_POP # else # define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) # endif @@ -873,70 +1197,6 @@ struct position_t # define JSON_HEDLEY_CPP_CAST(T, expr) (expr) #endif -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - defined(__clang__) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) - #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_PRAGMA(value) __pragma(value) -#else - #define JSON_HEDLEY_PRAGMA(value) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) - #undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#endif -#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) - #undef JSON_HEDLEY_DIAGNOSTIC_POP -#endif -#if defined(__clang__) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) - #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) -#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_PUSH - #define JSON_HEDLEY_DIAGNOSTIC_POP -#endif - #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED #endif @@ -944,12 +1204,18 @@ struct position_t #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") #elif \ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ @@ -982,6 +1248,8 @@ struct position_t #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) @@ -998,6 +1266,8 @@ struct position_t #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") #else #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS #endif @@ -1011,8 +1281,12 @@ struct position_t #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) @@ -1024,6 +1298,8 @@ struct position_t #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") #else #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES #endif @@ -1041,20 +1317,34 @@ struct position_t #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL #endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + #if defined(JSON_HEDLEY_DEPRECATED) #undef JSON_HEDLEY_DEPRECATED #endif #if defined(JSON_HEDLEY_DEPRECATED_FOR) #undef JSON_HEDLEY_DEPRECATED_FOR #endif -#if JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) -#elif defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) #elif \ - JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ @@ -1064,9 +1354,13 @@ struct position_t JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) #elif \ JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ @@ -1081,12 +1375,15 @@ struct position_t (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) #elif \ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) @@ -1103,7 +1400,8 @@ struct position_t #if \ JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) #else #define JSON_HEDLEY_UNAVAILABLE(available_since) @@ -1115,13 +1413,7 @@ struct position_t #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG #endif -#if (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) -#elif \ +#if \ JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ @@ -1137,9 +1429,16 @@ struct position_t JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) #elif defined(_Check_return_) /* SAL */ #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ @@ -1155,7 +1454,8 @@ struct position_t JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) #else #define JSON_HEDLEY_SENTINEL(position) @@ -1166,7 +1466,9 @@ struct position_t #endif #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) #define JSON_HEDLEY_NO_RETURN __noreturn -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define JSON_HEDLEY_NO_RETURN _Noreturn @@ -1188,11 +1490,14 @@ struct position_t (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") @@ -1224,7 +1529,8 @@ struct position_t #endif #if \ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_ASSUME(expr) __assume(expr) #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) @@ -1242,7 +1548,9 @@ struct position_t JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() #elif defined(JSON_HEDLEY_ASSUME) #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) @@ -1320,7 +1628,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) @@ -1356,15 +1665,16 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) #endif #if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) # define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) # define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) # define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) # define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) #elif \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ @@ -1378,7 +1688,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) # define JSON_HEDLEY_PREDICT(expr, expected, probability) \ (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) # define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ @@ -1424,11 +1735,14 @@ JSON_HEDLEY_DIAGNOSTIC_POP (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_MALLOC __declspec(restrict) #else #define JSON_HEDLEY_MALLOC @@ -1455,7 +1769,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) # define JSON_HEDLEY_PURE __attribute__((__pure__)) #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) # define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") @@ -1491,7 +1806,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_CONST __attribute__((__const__)) #elif \ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) @@ -1509,6 +1825,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ @@ -1518,7 +1835,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - defined(__clang__) + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_RESTRICT __restrict #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) #define JSON_HEDLEY_RESTRICT _Restrict @@ -1539,13 +1857,15 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define JSON_HEDLEY_INLINE __inline__ #elif \ JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_INLINE __inline #else #define JSON_HEDLEY_INLINE @@ -1571,9 +1891,13 @@ JSON_HEDLEY_DIAGNOSTIC_POP (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) # define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) # define JSON_HEDLEY_ALWAYS_INLINE __forceinline #elif defined(__cplusplus) && \ ( \ @@ -1611,9 +1935,13 @@ JSON_HEDLEY_DIAGNOSTIC_POP (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") @@ -1656,7 +1984,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ ) \ - ) + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) # define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) # define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) # else @@ -1672,10 +2001,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if \ JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) #elif \ JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) #define JSON_HEDLEY_NO_THROW __declspec(nothrow) #else @@ -1687,7 +2018,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) @@ -1704,7 +2036,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #if \ JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) #elif defined(_Ret_notnull_) /* SAL */ #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ @@ -1746,7 +2079,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) #endif #if !defined(__cplusplus) @@ -1770,7 +2104,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ !defined(JSON_HEDLEY_PGI_VERSION) && \ !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ @@ -1840,7 +2174,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if \ !defined(__cplusplus) && ( \ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ - JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ defined(_Static_assert) \ @@ -1848,7 +2182,8 @@ JSON_HEDLEY_DIAGNOSTIC_POP # define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) #elif \ (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) # define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) #else # define JSON_HEDLEY_STATIC_ASSERT(expr, message) @@ -1908,7 +2243,9 @@ JSON_HEDLEY_DIAGNOSTIC_POP JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) #else # define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) @@ -1944,8 +2281,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_FLAGS) #undef JSON_HEDLEY_FLAGS #endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS #endif #if defined(JSON_HEDLEY_FLAGS_CAST) @@ -1965,7 +2304,9 @@ JSON_HEDLEY_DIAGNOSTIC_POP #if defined(JSON_HEDLEY_EMPTY_BASES) #undef JSON_HEDLEY_EMPTY_BASES #endif -#if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0) +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) #else #define JSON_HEDLEY_EMPTY_BASES @@ -2020,9 +2361,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ -// This file contains all internal macro definitions +// This file contains all internal macro definitions (except those affecting ABI) // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them +// #include + + // exclude unsupported compilers #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) #if defined(__clang__) @@ -2037,30 +2381,128 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif // C++ language standard detection -#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) - #define JSON_HAS_CPP_20 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 -#elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 -#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE #endif -// disable float-equal warnings on GCC/clang -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wfloat-equal" +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS #endif // disable documentation warnings on clang #if defined(__clang__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" #endif -// allow to disable exceptions +// allow disabling exceptions #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) #define JSON_THROW(exception) throw exception #define JSON_TRY try @@ -2094,12 +2536,19 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER #endif -// allow to override assert +// allow overriding assert #if !defined(JSON_ASSERT) #include // assert #define JSON_ASSERT(x) assert(x) #endif +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + /*! @brief macro to briefly define a mapping between an enum and JSON @def NLOHMANN_JSON_SERIALIZE_ENUM @@ -2283,6 +2732,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); /*! @brief macro @@ -2293,6 +2743,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + /*! @brief macro @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE @@ -2302,6 +2756,49 @@ JSON_HEDLEY_DIAGNOSTIC_POP inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + #ifndef JSON_USE_IMPLICIT_CONVERSIONS #define JSON_USE_IMPLICIT_CONVERSIONS 1 #endif @@ -2312,406 +2809,383 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define JSON_EXPLICIT explicit #endif +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif -namespace nlohmann -{ +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { -//////////////// -// exceptions // -//////////////// + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// /*! -@brief general exception of the @ref basic_json class +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. -This class is an extension of `std::exception` objects with a member @a id for -exception ids. It is used as the base class for all exceptions thrown by the -@ref basic_json class. This class can hence be used as "wildcard" to catch -exceptions. +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. -Subclasses: -- @ref parse_error for exceptions indicating a parse error -- @ref invalid_iterator for exceptions indicating errors with iterators -- @ref type_error for exceptions indicating executing a member function with - a wrong type -- @ref out_of_range for exceptions indicating access out of the defined range -- @ref other_error for exceptions indicating other library errors +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type -@internal -@note To have nothrow-copy-constructible exceptions, we internally use - `std::runtime_error` which can cope with arbitrary-length error messages. - Intermediate strings are built with static functions and then passed to - the actual constructor. -@endinternal +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types -@liveexample{The following code shows how arbitrary library exceptions can be -caught.,exception} +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. -@since version 3.0.0 +@since version 1.0.0 */ -class exception : public std::exception +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif { - public: - /// returns the explanatory string - JSON_HEDLEY_RETURNS_NON_NULL - const char* what() const noexcept override + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) { - return m.what(); + return order[l_index] <=> order[r_index]; // *NOPAD* } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} - /// the id of the exception - const int id; +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif - protected: - JSON_HEDLEY_NON_NULL(3) - exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END - static std::string name(const std::string& ename, int id_) - { - return "[json.exception." + ename + "." + std::to_string(id_) + "] "; - } +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT - private: - /// an exception object as storage for error messages - std::runtime_error m; -}; -/*! -@brief exception indicating a parse error - -This exception is thrown by the library when a parse error occurs. Parse errors -can occur during the deserialization of JSON text, CBOR, MessagePack, as well -as when using JSON Patch. - -Member @a byte holds the byte index of the last read character in the input -file. - -Exceptions have ids 1xx. - -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. -json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. -json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. -json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. -json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. -json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. -json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. -json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. -json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. -json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. -json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. -json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. -json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). -json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed. - -@note For an input with n bytes, 1 is the index of the first character and n+1 - is the index of the terminating null byte or the end of file. This also - holds true when reading a byte vector (CBOR or MessagePack). - -@liveexample{The following code shows how a `parse_error` exception can be -caught.,parse_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class parse_error : public exception -{ - public: - /*! - @brief create a parse error exception - @param[in] id_ the id of the exception - @param[in] pos the position where the error occurred (or with - chars_read_total=0 if the position cannot be - determined) - @param[in] what_arg the explanatory string - @return parse_error object - */ - static parse_error create(int id_, const position_t& pos, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + what_arg; - return parse_error(id_, pos.chars_read_total, w.c_str()); - } - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + what_arg; - return parse_error(id_, byte_, w.c_str()); - } +// #include - /*! - @brief byte index of the parse error - The byte index of the last read character in the input file. +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ - @note For an input with n bytes, 1 is the index of the first character and - n+1 is the index of the terminating null byte or the end of file. - This also holds true when reading a byte vector (CBOR or MessagePack). - */ - const std::size_t byte; +/*! +@brief replace all occurrences of a substring by another string - private: - parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f - static std::string position_string(const position_t& pos) - { - return " at line " + std::to_string(pos.lines_read + 1) + - ", column " + std::to_string(pos.chars_read_current_line); - } -}; +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** -/*! -@brief exception indicating errors with iterators - -This exception is thrown if iterators passed to a library function do not match -the expected semantics. - -Exceptions have ids 2xx. - -name / id | example message | description ------------------------------------ | --------------- | ------------------------- -json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. -json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. -json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. -json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. -json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. -json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. -json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. -json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. -json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). - -@liveexample{The following code shows how an `invalid_iterator` exception can be -caught.,invalid_iterator} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 +@since version 2.0.0 */ -class invalid_iterator : public exception +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) { - public: - static invalid_iterator create(int id_, const std::string& what_arg) - { - std::string w = exception::name("invalid_iterator", id_) + what_arg; - return invalid_iterator(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) {} -}; + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} /*! -@brief exception indicating executing a member function with a wrong type - -This exception is thrown in case of a type error; that is, a library function is -executed on a JSON value whose type does not match the expected semantics. - -Exceptions have ids 3xx. - -name / id | example message | description ------------------------------ | --------------- | ------------------------- -json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. -json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. -json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. -json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. -json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. -json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. -json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. -json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. -json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. -json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. -json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. -json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. -json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. -json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. -json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | -json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | - -@liveexample{The following code shows how a `type_error` exception can be -caught.,type_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class type_error : public exception + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) { - public: - static type_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("type_error", id_) + what_arg; - return type_error(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} /*! -@brief exception indicating access out of the defined range - -This exception is thrown in case a library function is called on an input -parameter that exceeds the expected range, for instance in case of array -indices or nonexisting object keys. - -Exceptions have ids 4xx. - -name / id | example message | description -------------------------------- | --------------- | ------------------------- -json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. -json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. -json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. -json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. -json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. -json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. -json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) | -json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | -json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | - -@liveexample{The following code shows how an `out_of_range` exception can be -caught.,out_of_range} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class out_of_range : public exception + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +static void unescape(StringType& s) { - public: - static out_of_range create(int id_, const std::string& what_arg) - { - std::string w = exception::name("out_of_range", id_) + what_arg; - return out_of_range(id_, w.c_str()); - } + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} - private: - JSON_HEDLEY_NON_NULL(3) - out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END -/*! -@brief exception indicating other library errors +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -This exception is thrown in case of errors that cannot be classified with the -other exception types. -Exceptions have ids 5xx. -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. +#include // size_t -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range +// #include -@liveexample{The following code shows how an `other_error` exception can be -caught.,other_error} -@since version 3.0.0 -*/ -class other_error : public exception +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail { - public: - static other_error create(int id_, const std::string& what_arg) + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const { - std::string w = exception::name("other_error", id_) + what_arg; - return other_error(id_, w.c_str()); + return chars_read_total; } - - private: - JSON_HEDLEY_NON_NULL(3) - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} }; + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + +#include // array #include // size_t #include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for -namespace nlohmann -{ +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + // alias templates to reduce boilerplate template using enable_if_t = typename std::enable_if::type; -template -using uncvref_t = typename std::remove_cv::type>::type; +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL -// implementation of C++14 index_sequence and affiliates -// source: https://stackoverflow.com/a/32223343 -template -struct index_sequence +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence { - using type = index_sequence; - using value_type = std::size_t; + using value_type = T; static constexpr std::size_t size() noexcept { return sizeof...(Ints); } }; -template -struct merge_and_renumber; +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal -template -struct merge_and_renumber, index_sequence> - : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; +// Compile-time sequences of integers -template -struct make_index_sequence - : merge_and_renumber < typename make_index_sequence < N / 2 >::type, - typename make_index_sequence < N - N / 2 >::type > {}; +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; -template<> struct make_index_sequence<0> : index_sequence<> {}; -template<> struct make_index_sequence<1> : index_sequence<0> {}; +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; -template +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template using index_sequence_for = make_index_sequence; +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + // dispatch utility (taken from ranges-v3) template struct priority_tag : priority_tag < N - 1 > {}; template<> struct priority_tag<0> {}; @@ -2720,48 +3194,63 @@ template<> struct priority_tag<0> {}; template struct static_const { - static constexpr T value{}; + static JSON_INLINE_VARIABLE constexpr T value{}; }; -template -constexpr T static_const::value; +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + } // namespace detail -} // namespace nlohmann +NLOHMANN_JSON_NAMESPACE_END // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #include // numeric_limits #include // false_type, is_constructible, is_integral, is_same, true_type #include // declval +#include // tuple // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -#include // random_access_iterator_tag -// #include +#include // random_access_iterator_tag +// #include -namespace nlohmann -{ -namespace detail -{ -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; -} // namespace detail -} // namespace nlohmann +// #include // #include -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { + template struct iterator_types {}; @@ -2800,157 +3289,135 @@ struct iterator_traits::value>> using pointer = T*; using reference = T&; }; -} // namespace detail -} // namespace nlohmann + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END // #include -// #include +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -// #include -#include +// #include -// #include +NLOHMANN_JSON_NAMESPACE_BEGIN -// https://en.cppreference.com/w/cpp/experimental/is_detected -namespace nlohmann -{ -namespace detail -{ -struct nonesuch -{ - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; +NLOHMANN_JSON_NAMESPACE_END -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT -template class Op, class... Args> -using is_detected = typename detector::value_t; -template class Op, class... Args> -using detected_t = typename detector::type; -template class Op, class... Args> -using detected_or = detector; +// #include -template class Op, class... Args> -using detected_or_t = typename detected_or::type; -template class Op, class... Args> -using is_detected_exact = std::is_same>; +NLOHMANN_JSON_NAMESPACE_BEGIN -template class Op, class... Args> -using is_detected_convertible = - std::is_convertible, To>; -} // namespace detail -} // namespace nlohmann +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include // #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#include // int64_t, uint64_t -#include // map -#include // allocator -#include // string -#include // vector + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -namespace nlohmann -{ -/*! -@brief default JSONSerializer template argument + // #include -This serializer ignores the template arguments and uses ADL -([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) -for serialization. -*/ -template -struct adl_serializer; - -template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector> -class basic_json; -/*! -@brief JSON Pointer + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN -A JSON pointer defines a string syntax for identifying a specific value -within a JSON document. It can be used with functions `at` and -`operator[]`. Furthermore, JSON pointers are the base for JSON patches. + /*! + @brief default JSONSerializer template argument -@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; -@since version 2.0.0 -*/ -template -class json_pointer; + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector> + class basic_json; -/*! -@brief default JSON class + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; -This type is the default specialization of the @ref basic_json class which -uses the standard template types. + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; -@since version 1.0.0 -*/ -using json = basic_json<>; + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; -template -struct ordered_map; + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; -/*! -@brief ordered JSON class - -This type preserves the insertion order of object keys. - -@since version 3.9.0 -*/ -using ordered_json = basic_json; - -} // namespace nlohmann + NLOHMANN_JSON_NAMESPACE_END #endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ -namespace nlohmann -{ +NLOHMANN_JSON_NAMESPACE_BEGIN /*! @brief detail namespace with internal helper functions @@ -2961,6 +3428,7 @@ implementations of some @ref basic_json methods, and meta-programming helpers. */ namespace detail { + ///////////// // helpers // ///////////// @@ -2979,6 +3447,16 @@ template struct is_basic_json : std::false_type {}; NLOHMANN_BASIC_JSON_TPL_DECLARATION struct is_basic_json : std::true_type {}; +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + ////////////////////// // json_ref helpers // ////////////////////// @@ -3017,9 +3495,6 @@ using reference_t = typename T::reference; template using iterator_category_t = typename T::iterator_category; -template -using iterator_t = typename T::iterator; - template using to_json_function = decltype(T::to_json(std::declval()...)); @@ -3044,8 +3519,7 @@ struct is_getable }; template -struct has_from_json < BasicJsonType, T, - enable_if_t < !is_basic_json::value >> +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> { using serializer = typename BasicJsonType::template json_serializer; @@ -3084,11 +3558,78 @@ struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> T>::value; }; +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; /////////////////// // is_ functions // /////////////////// +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + + template struct is_iterator_traits : std::false_type {}; @@ -3107,7 +3648,34 @@ struct is_iterator_traits> is_detected::value; }; -// source: https://stackoverflow.com/a/37193089/4116453 +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. template struct is_complete_type : std::false_type {}; @@ -3125,14 +3693,13 @@ struct is_compatible_object_type_impl < enable_if_t < is_detected::value&& is_detected::value >> { - using object_t = typename BasicJsonType::object_t; // macOS's is_constructible does not play well with nonesuch... static constexpr bool value = - std::is_constructible::value && - std::is_constructible::value; }; @@ -3153,10 +3720,10 @@ struct is_constructible_object_type_impl < using object_t = typename BasicJsonType::object_t; static constexpr bool value = - (std::is_default_constructible::value && + (is_default_constructible::value && (std::is_move_assignable::value || std::is_copy_assignable::value) && - (std::is_constructible::value && std::is_same < typename object_t::mapped_type, @@ -3173,60 +3740,46 @@ struct is_constructible_object_type : is_constructible_object_type_impl {}; -template -struct is_compatible_string_type_impl : std::false_type {}; - template -struct is_compatible_string_type_impl < - BasicJsonType, CompatibleStringType, - enable_if_t::value >> +struct is_compatible_string_type { static constexpr auto value = - std::is_constructible::value; + is_constructible::value; }; template -struct is_compatible_string_type - : is_compatible_string_type_impl {}; - -template -struct is_constructible_string_type_impl : std::false_type {}; - -template -struct is_constructible_string_type_impl < - BasicJsonType, ConstructibleStringType, - enable_if_t::value >> +struct is_constructible_string_type { + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + static constexpr auto value = - std::is_constructible::value; + conjunction < + is_constructible, + is_detected_exact>::value; }; -template -struct is_constructible_string_type - : is_constructible_string_type_impl {}; - template struct is_compatible_array_type_impl : std::false_type {}; template struct is_compatible_array_type_impl < BasicJsonType, CompatibleArrayType, - enable_if_t < is_detected::value&& + enable_if_t < is_detected::value&& -// This is needed because json_reverse_iterator has a ::iterator type... -// Therefore it is detected as a CompatibleArrayType. -// The real fix would be to have an Iterable concept. - !is_iterator_traits < - iterator_traits>::value >> + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> { static constexpr bool value = - std::is_constructible::value; + is_constructible>::value; }; template @@ -3248,28 +3801,29 @@ struct is_constructible_array_type_impl < BasicJsonType, ConstructibleArrayType, enable_if_t < !std::is_same::value&& - std::is_default_constructible::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& (std::is_move_assignable::value || std::is_copy_assignable::value)&& -is_detected::value&& is_detected::value&& -is_complete_type < -detected_t>::value >> +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> { + using value_type = range_value_t; + static constexpr bool value = - // This is needed because json_reverse_iterator has a ::iterator type, - // furthermore, std::back_insert_iterator (and other iterators) have a - // base class `iterator`... Therefore it is detected as a - // ConstructibleArrayType. The real fix would be to have an Iterable - // concept. - !is_iterator_traits>::value && - - (std::is_same::value || - has_from_json::value || - has_non_default_from_json < - BasicJsonType, typename ConstructibleArrayType::value_type >::value); + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; }; template @@ -3292,7 +3846,7 @@ struct is_compatible_integer_type_impl < using CompatibleLimits = std::numeric_limits; static constexpr auto value = - std::is_constructible::value && CompatibleLimits::is_integer && RealLimits::is_signed == CompatibleLimits::is_signed; @@ -3319,221 +3873,843 @@ template struct is_compatible_type : is_compatible_type_impl {}; -// https://en.cppreference.com/w/cpp/types/conjunction -template struct conjunction : std::true_type { }; -template struct conjunction : B1 { }; -template -struct conjunction -: std::conditional, B1>::type {}; - template struct is_constructible_tuple : std::false_type {}; template -struct is_constructible_tuple> : conjunction...> {}; -} // namespace detail -} // namespace nlohmann +struct is_constructible_tuple> : conjunction...> {}; -// #include +template +struct is_json_iterator_of : std::false_type {}; +template +struct is_json_iterator_of : std::true_type {}; -#include // array -#include // size_t -#include // uint8_t -#include // string +template +struct is_json_iterator_of : std::true_type +{}; -namespace nlohmann -{ -namespace detail -{ -/////////////////////////// -// JSON type enumeration // -/////////////////////////// +// checks if a given type T is a template specialization of Primary +template