From 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d Mon Sep 17 00:00:00 2001 From: Jef Date: Tue, 24 Sep 2024 14:54:57 +0200 Subject: Initial community commit --- Src/Plugins/Library/ml_webdev/navigation.cpp | 1261 ++++++++++++++++++++++++++ 1 file changed, 1261 insertions(+) create mode 100644 Src/Plugins/Library/ml_webdev/navigation.cpp (limited to 'Src/Plugins/Library/ml_webdev/navigation.cpp') diff --git a/Src/Plugins/Library/ml_webdev/navigation.cpp b/Src/Plugins/Library/ml_webdev/navigation.cpp new file mode 100644 index 00000000..ebbe555f --- /dev/null +++ b/Src/Plugins/Library/ml_webdev/navigation.cpp @@ -0,0 +1,1261 @@ +#include "main.h" +#include "./navigation.h" +#include "./resource.h" +#include "./wasabi.h" +#include "./local_menu.h" +#include "./commands.h" +#include "./forceUrl.h" +#include "./config.h" + +#include "../omBrowser/browserView.h" +#include "../winamp/wa_ipc.h" + +#include "./serviceHost.h" +#include "./serviceHelper.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define _ML_HEADER_IMPMLEMENT +#include "../../General/gen_ml/ml_ipc_0313.h" +#undef _ML_HEADER_IMPMLEMENT +#include "../../General/gen_ml/menu.h" + +#include +#include "../nu/sort.h" + +#include +#include +#include + +#define NAVITEM_PREFIX L"webdev_svc_" +#define E_NAVITEM_UNKNOWN E_NOINTERFACE + + +static BOOL Navigation_CheckInvariantName(LPCWSTR pszInvarian) +{ + INT cchInvariant = (NULL != pszInvarian) ? lstrlen(pszInvarian) : 0; + INT cchPrefix = ARRAYSIZE(NAVITEM_PREFIX) - 1; + return (cchInvariant > cchPrefix && + CSTR_EQUAL == CompareString(CSTR_INVARIANT, 0, NAVITEM_PREFIX, cchPrefix, pszInvarian, cchPrefix)); +} + + +Navigation::Navigation() + : ref(1), cookie(0), hRoot(NULL), hLibrary(NULL) +{ +} + +Navigation::~Navigation() +{ +} + +HRESULT Navigation::CreateInstance(Navigation **instance) +{ + if (NULL == instance) return E_POINTER; + + HRESULT hr; + + Navigation *navigation = new Navigation(); + if (NULL != navigation) + { + hr = navigation->Initialize(); + if (FAILED(hr)) + { + navigation->Release(); + navigation = NULL; + } + } + else + { + hr = E_OUTOFMEMORY; + } + + *instance = navigation; + return hr; +} + +size_t Navigation::AddRef() +{ + return InterlockedIncrement((LONG*)&ref); +} + +size_t Navigation::Release() +{ + if (0 == ref) + return ref; + + LONG r = InterlockedDecrement((LONG*)&ref); + if (0 == r) + delete(this); + + return r; +} + +int Navigation::QueryInterface(GUID interface_guid, void **object) +{ + if (NULL == object) return E_POINTER; + + if (IsEqualIID(interface_guid, IFC_MlNavigationCallback)) + *object = static_cast(this); + else + { + *object = NULL; + return E_NOINTERFACE; + } + if (NULL == *object) + return E_UNEXPECTED; + + AddRef(); + return S_OK; +} + +HRESULT Navigation::Initialize() +{ + hLibrary = Plugin_GetLibrary(); + if (NULL == hLibrary) return E_UNEXPECTED; + + if (0 == cookie) + { + ifc_mlnavigationhelper *navHelper; + if (NULL != OMUTILITY && SUCCEEDED(OMUTILITY->GetMlNavigationHelper(Plugin_GetLibrary(), &navHelper))) + { + navHelper->RegisterCallback(this, &cookie); + navHelper->Release(); + } + } + + ifc_omservice *service; + + MLNavCtrl_BeginUpdate(hLibrary, NUF_LOCK_TOP); + + if (SUCCEEDED(ServiceHelper_Create(700, MAKEINTRESOURCE(IDS_ROOTSERVICE_NAME), + NULL, MAKEINTRESOURCE(IDR_HTML_WELCOME), + WDSVCF_ROOT, FALSE, &service))) + { + hRoot = CreateItemInt(NULL, service); + service->Release(); + } + + if (NULL == hRoot) + { + MLNavCtrl_EndUpdate(hLibrary); + return E_FAIL; + } + + + if (SUCCEEDED(ServiceHelper_Create(701, MAKEINTRESOURCE(IDS_DOCSERVICE_NAME), + MAKEINTRESOURCE(IDR_HELP_ICON), L"http://dev.winamp.com/online-service-developers", + WDSVCF_SPECIAL, FALSE, &service))) + { + CreateItemInt(hRoot, service); + service->Release(); + } + + if (SUCCEEDED(ServiceHelper_Create(702, MAKEINTRESOURCE(IDS_TESTSERVICE_NAME), + MAKEINTRESOURCE(IDR_GEAR_ICON), MAKEINTRESOURCE(IDR_HTML_TEST), + WDSVCF_SPECIAL, FALSE, &service))) + { + CreateItemInt(hRoot, service); + service->Release(); + } + + ifc_omstorage *storage; + if (NULL != OMSERVICEMNGR && SUCCEEDED(OMSERVICEMNGR->QueryStorage(&SUID_OmStorageIni, &storage))) + { + ifc_omserviceenum *enumerator; + WebDevServiceHost *serviceHost; + if (FAILED(WebDevServiceHost::GetCachedInstance(&serviceHost))) + serviceHost = NULL; + + if (SUCCEEDED(storage->Load(L"*.ini", serviceHost, &enumerator))) + { + ifc_omservice *service; + std::vector serviceList; + while (S_OK == enumerator->Next(1, &service, NULL)) + { + serviceList.push_back(service); + } + enumerator->Release(); + + size_t count = serviceList.size(); + Order(serviceList); + for(size_t i =0; i < count; i++) + { + service = serviceList[i]; + CreateItemInt(hRoot, service); + service->Release(); + } + } + storage->Release(); + + if (NULL != serviceHost) + serviceHost->Release(); + } + + MLNavCtrl_EndUpdate(hLibrary); + + return S_OK; +} + +HRESULT Navigation::Finish() +{ + ForceUrl_Remove(); + + if (0 != cookie) + { + ifc_mlnavigationhelper *navHelper; + if (NULL != OMUTILITY && SUCCEEDED(OMUTILITY->GetMlNavigationHelper(Plugin_GetLibrary(), &navHelper))) + { + navHelper->UnregisterCallback(cookie); + navHelper->Release(); + } + } + + if (NULL != OMBROWSERMNGR) + { + OMBROWSERMNGR->Finish(); + } + + return S_OK; +} + +HRESULT Navigation::SaveOrder() +{ + if (NULL == hRoot || NULL == hLibrary) + return E_UNEXPECTED; + + LPSTR buffer = NULL; + INT count = MLNavItem_GetChildrenCount(hLibrary, hRoot); + if (count > 0) + { + size_t bufferMax = 11 * count; + buffer = Plugin_MallocAnsiString(bufferMax); + if (NULL == buffer) return E_OUTOFMEMORY; + *buffer = '\0'; + + LPSTR cursor = buffer; + size_t remaining = bufferMax; + + NAVITEM item; + item.cbSize = sizeof(item); + item.mask = NIMF_PARAM; + item.hItem = MLNavItem_GetChild(hLibrary, hRoot); + while (NULL != item.hItem) + { + if (FALSE != MLNavItem_GetInfo(hLibrary, &item)) + { + ifc_omservice *service = (ifc_omservice*)item.lParam; + if (NULL != service) + { + UINT serviceFlags; + if (SUCCEEDED(service->GetFlags(&serviceFlags)) && + 0 == ((WDSVCF_ROOT | WDSVCF_SPECIAL) & serviceFlags)) + { + if (cursor == buffer || + SUCCEEDED(StringCchCopyExA(cursor, remaining, ";", &cursor, &remaining, STRSAFE_NULL_ON_FAILURE))) + { + StringCchPrintfExA(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE, "%d", service->GetId()); + } + } + } + } + item.hItem = MLNavItem_GetNext(hLibrary, item.hItem); + } + + } + + Config_WriteStr("Navigation", "order", buffer); + Plugin_FreeAnsiString(buffer); + + return S_OK; +} + +//static int __fastcall Navigation_OrderComparer(const void *elem1, const void *elem2, const void *context) +//{ +// std::vector *orderList = (std::vector*)context; +// +// UINT serviceId; +// size_t index1, index2; +// size_t count = orderList->size(); +// +// serviceId = (*(ifc_omservice**)elem1)->GetId(); +// for (index1 = 0; index1 < count && serviceId != orderList->at(index1); index1++); +// +// serviceId = (*(ifc_omservice**)elem2)->GetId(); +// for (index2 = 0; index2 < count && serviceId != orderList->at(index2); index2++); +// +// return (INT)(index1 - index2); +//} +class Navigation_OrderComparer +{ +public: + Navigation_OrderComparer(const void* ctx) + : context(ctx) + { + } + + bool operator()(const void* elem1, const void* elem2) + { + std::vector* orderList = (std::vector*)context; + + UINT serviceId; + size_t index1, index2; + size_t count = orderList->size(); + + serviceId = ((ifc_omservice*)elem1)->GetId(); + for (index1 = 0; index1 < count && serviceId != orderList->at(index1); index1++); + + serviceId = ((ifc_omservice*)elem2)->GetId(); + for (index2 = 0; index2 < count && serviceId != orderList->at(index2); index2++); + + return (INT)(index1 - index2) < 0; + } + + +private: + const void* context; +}; +HRESULT Navigation::Order(std::vector &list) +{ + size_t listSize = list.size(); + + if (listSize < 2) + return S_FALSE; + + //if (NULL == list) return E_INVALIDARG; + + size_t bufferMax = 16384; + LPSTR buffer = Plugin_MallocAnsiString(bufferMax); + if (NULL == buffer) return E_OUTOFMEMORY; + + UINT len = Config_ReadStr("Navigation", "order", NULL, buffer, (UINT)bufferMax); + std::vector orderList; + + LPCSTR end = buffer + len; + LPCSTR block = buffer; + LPCSTR cursor = block; + for(;;) + { + if (cursor == end || ';' == *cursor) + { + if (block != cursor) + { + INT serviceId; + if (FALSE != StrToIntExA(block, STIF_DEFAULT, &serviceId)) + orderList.push_back(serviceId); + } + + if (cursor == end) break; + cursor++; + block = cursor; + } + cursor++; + } + + + if (0 != orderList.size()) + { + //nu::qsort(list, listSize, sizeof(ifc_omservice*), &orderList, Navigation_OrderComparer); + std::sort(list.begin(), list.end(), Navigation_OrderComparer(&orderList)); + } + + Plugin_FreeAnsiString(buffer); + return S_OK; +} + +void Navigation::ImageChanged(LPCWSTR pszName, INT index) +{ + if (NULL == hRoot || NULL == hLibrary || NULL == pszName) + return; + + WCHAR szBuffer[2048] = {0}; + NAVITEM item = {0}; + item.cbSize = sizeof(item); + item.mask = NIMF_TEXTINVARIANT | NIMF_PARAM; + item.pszInvariant = szBuffer; + item.cchInvariantMax = ARRAYSIZE(szBuffer); + + item.hItem = hRoot; + + while (NULL != item.hItem) + { + if (FALSE != MLNavItem_GetInfo(hLibrary, &item) && + FALSE != Navigation_CheckInvariantName(item.pszInvariant)) + { + ifc_omservice *service = (ifc_omservice*)item.lParam; + if (NULL != service && + SUCCEEDED(service->GetIcon(szBuffer, ARRAYSIZE(szBuffer))) && + CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, szBuffer, -1, pszName, -1)) + { + + item.iImage = index; + item.iSelectedImage = index; + item.mask = NIMF_IMAGE | NIMF_IMAGESEL; + MLNavItem_SetInfo(hLibrary, &item); + return; + } + } + + item.hItem = (HNAVITEM)SENDMLIPC(hLibrary, + (item.hItem == hRoot) ? ML_IPC_NAVITEM_GETCHILD : ML_IPC_NAVITEM_GETNEXT, + (WPARAM)item.hItem); + + } +} + + + +BOOL Navigation::ProcessMessage(INT msg, INT_PTR param1, INT_PTR param2, INT_PTR param3, INT_PTR *result) +{ + if (msg == ML_MSG_NO_CONFIG) + { + *result = TRUE; + return TRUE; + } + + if (msg < ML_MSG_TREE_BEGIN || msg > ML_MSG_TREE_END) + return FALSE; + + HRESULT hr; + + switch(msg) + { + case ML_MSG_TREE_ONCREATEVIEW: + { + HWND hView; + hr = OnCreateView(GetMessageItem(msg, param1), (HWND)param2, &hView); + *result = (SUCCEEDED(hr)) ? (INT_PTR)hView : NULL; + } + return TRUE; + + case ML_MSG_NAVIGATION_CONTEXTMENU: + hr = OnContextMenu(GetMessageItem(msg, param1), (HWND)param2, MAKEPOINTS(param3)); + *result = SUCCEEDED(hr); + return TRUE; + + case ML_MSG_NAVIGATION_ONDELETE: + hr = OnDeleteItem(GetMessageItem(msg, param1)); + *result = SUCCEEDED(hr); + return TRUE; + + case ML_MSG_NAVIGATION_ONENDTITLEEDIT: + hr = OnEndTitleEdit(GetMessageItem(msg, param1), (LPCWSTR)param2); + *result = SUCCEEDED(hr); + return TRUE; + + case ML_MSG_TREE_ONKEYDOWN: + hr = OnKeyDown(GetMessageItem(msg, param1), (NMTVKEYDOWN*)param2); + *result = SUCCEEDED(hr); + return TRUE; + + case ML_MSG_NAVIGATION_ONDESTROY: + OnControlDestroy(); + *result = 0; + return TRUE; + } + + return FALSE; +} + +HNAVITEM Navigation::GetActive(ifc_omservice **serviceOut) +{ + ifc_omservice *service; + HNAVITEM hActive = (NULL != hLibrary) ? MLNavCtrl_GetSelection(hLibrary) : NULL; + if (NULL == hActive || FAILED(GetService(hActive, &service))) + { + hActive = NULL; + service = NULL; + } + + if (NULL != serviceOut) + *serviceOut = service; + else if (NULL != service) + service->Release(); + + return hActive; +} + +HWND Navigation::GetActiveView(ifc_omservice **serviceOut) +{ + HWND hView = (NULL != hLibrary) ? ((HWND)SENDMLIPC(hLibrary, ML_IPC_GETCURRENTVIEW, 0)) : NULL; + if (NULL != hView) + { + WCHAR szBuffer[128] = {0}; + if (!GetClassName(hView, szBuffer, ARRAYSIZE(szBuffer)) || + CSTR_EQUAL != CompareStringW(CSTR_INVARIANT, NORM_IGNORECASE, szBuffer, -1, + L"Nullsoft_omBrowserView", -1)) + { + hView = NULL; + } + } + + ifc_omservice *service; + if (NULL == hView || FALSE == BrowserView_GetService(hView, &service)) + { + hView = NULL; + service = NULL; + } + + if (NULL != serviceOut) + *serviceOut = service; + else if (NULL != service) + service->Release(); + + return hView; +} + +HRESULT Navigation::SelectItem(HNAVITEM hItem, LPCWSTR pszUrl) +{ + if (NULL == hItem) return E_INVALIDARG; + + ifc_omservice *service; + HRESULT hr = GetService(hItem, &service); + if (FAILED(hr)) return hr; + + hr = SelectItemInt(hItem, service->GetId(), pszUrl); + service->Release(); + + return hr; +} + +HRESULT Navigation::DeleteItem(HNAVITEM hItem) +{ + if (NULL == hItem) return E_INVALIDARG; + if (NULL == hLibrary) return E_UNEXPECTED; + + ifc_omservice *service; + if (FAILED(GetService(hItem, &service))) + return E_FAIL; + + UINT serviceFlags; + if (FAILED(service->GetFlags(&serviceFlags))) serviceFlags = 0; + if (0 != ((WDSVCF_ROOT | WDSVCF_SPECIAL) & serviceFlags)) + return E_NOTIMPL; + + MLNavCtrl_BeginUpdate(hLibrary, 0); + HNAVITEM hSelection = MLNavCtrl_GetSelection(hLibrary); + if (hSelection == hItem) + { + HNAVITEM hNext = MLNavItem_GetNext(hLibrary, hItem); + if (NULL == hNext) + hNext = MLNavItem_GetPrevious(hLibrary, hItem); + + if (NULL != hNext) + { + MLNavItem_Select(hLibrary, hNext); + } + } + + BOOL result = MLNavCtrl_DeleteItem(hLibrary, hItem); + HRESULT hr = (FALSE != result) ? S_OK : E_FAIL; + + MLNavCtrl_EndUpdate(hLibrary); + + if (SUCCEEDED(hr)) + ServiceHelper_Delete(service); + + service->Release(); + + return hr; +} + +HRESULT Navigation::DeleteAll() +{ + if (NULL == hRoot || NULL == hLibrary) return E_UNEXPECTED; + + std::vector itemList; + HNAVITEM hItem = MLNavItem_GetChild(hLibrary, hRoot); + while (NULL != hItem) + { + itemList.push_back(hItem); + hItem = MLNavItem_GetNext(hLibrary, hItem); + } + + MLNavCtrl_BeginUpdate(hLibrary, 0); + + NAVITEM item; + item.cbSize = sizeof(item); + item.mask = NIMF_PARAM; + + size_t index = itemList.size(); + while(index--) + { + item.hItem = itemList[index]; + if (FALSE != MLNavItem_GetInfo(hLibrary, &item)) + { + ifc_omservice *service = (ifc_omservice*)item.lParam; + if (NULL != service) + { + service->AddRef(); + + UINT serviceFlags; + if (SUCCEEDED(service->GetFlags(&serviceFlags)) && + 0 == ((WDSVCF_ROOT | WDSVCF_SPECIAL) & serviceFlags) && + FALSE != MLNavCtrl_DeleteItem(hLibrary, item.hItem)) + { + ServiceHelper_Delete(service); + } + + service->Release(); + } + } + } + + MLNavCtrl_EndUpdate(hLibrary); + return S_OK; +} + +HRESULT Navigation::CreatePopup(HNAVITEM hItem, HWND *hwnd) +{ + if (NULL == hwnd) return E_POINTER; + *hwnd = NULL; + + if (NULL == hLibrary) return E_UNEXPECTED; + if (NULL == hItem) return E_INVALIDARG; + + HRESULT hr; + + ifc_omservice *service; + hr = GetService(hItem, &service); + if (SUCCEEDED(hr)) + { + HWND hWinamp = Plugin_GetWinamp(); + + if (NULL == OMBROWSERMNGR) + hr = E_UNEXPECTED; + + if (SUCCEEDED(hr)) + { + hr = OMBROWSERMNGR->Initialize(NULL, hWinamp); + if (SUCCEEDED(hr)) + { + RECT rect; + HWND hFrame = (HWND)SENDMLIPC(hLibrary, ML_IPC_GETCURRENTVIEW, 0); + if (NULL == hFrame) hFrame = hLibrary; + if (NULL == hFrame || FALSE == GetWindowRect(hFrame, &rect)) + { + hr = E_FAIL; + } + + if (SUCCEEDED(hr)) + { + rect.left += 16; + rect.top += 16; + + hr = OMBROWSERMNGR->CreatePopup(service, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, hWinamp, NULL, 0, hwnd); + } + } + } + service->Release(); + } + return hr; +} + +HRESULT Navigation::GetService(HNAVITEM hItem, ifc_omservice **service) +{ + WCHAR szBuffer[64] = {0}; + + if (NULL == service) return E_POINTER; + *service = NULL; + + if (NULL == hLibrary || NULL == hItem) + return E_INVALIDARG; + + NAVITEM itemInfo; + itemInfo.cbSize = sizeof(NAVITEM); + itemInfo.hItem = hItem; + itemInfo.pszInvariant = szBuffer; + itemInfo.cchInvariantMax = ARRAYSIZE(szBuffer); + itemInfo.mask = NIMF_PARAM | NIMF_TEXTINVARIANT; + + if (FALSE == MLNavItem_GetInfo(hLibrary, &itemInfo)) + return E_FAIL; + + if (FALSE == Navigation_CheckInvariantName(szBuffer)) + return E_NAVITEM_UNKNOWN; + + *service = (ifc_omservice*)itemInfo.lParam; + (*service)->AddRef(); + return S_OK; +} + +static void CALLBACK Navigtaion_UpdateServiceApc(Dispatchable *object, ULONG_PTR param1, ULONG_PTR param2) +{ + Navigation *navigation = (Navigation*)object; + if (NULL != navigation) + { + ifc_omservice *service = (ifc_omservice*)param1; + navigation->UpdateService(service, (UINT)param2); + if (NULL != service) service->Release(); + } +} + +HRESULT Navigation::UpdateService(ifc_omservice *service, UINT modifiedFlags) +{ + if (NULL == hLibrary) return E_UNEXPECTED; + + DWORD libraryTID = GetWindowThreadProcessId(hLibrary, NULL); + DWORD currentTID = GetCurrentThreadId(); + if (libraryTID != currentTID) + { + if (NULL != OMUTILITY) + { + service->AddRef(); + if (FAILED(OMUTILITY->PostMainThreadCallback2(Navigtaion_UpdateServiceApc, this, (ULONG_PTR)service, (ULONG_PTR)modifiedFlags))) + service->Release(); + } + return E_PENDING; + } + + HNAVITEM hItem = FindService(service->GetId(), NULL); + if (NULL == hItem) + return E_FAIL; + + NAVITEM itemInfo; + itemInfo.cbSize = sizeof(NAVITEM); + itemInfo.hItem = hItem; + + itemInfo.mask = NIMF_IMAGE; + if (FALSE == MLNavItem_GetInfo(hLibrary, &itemInfo)) + itemInfo.iImage= -1; + + itemInfo.mask = 0; + + WCHAR szName[512] = {0}; + if (0 != (ifc_omserviceeditor::modifiedName & modifiedFlags) && + SUCCEEDED(service->GetName(szName, ARRAYSIZE(szName)))) + { + itemInfo.mask |= NIMF_TEXT; + itemInfo.pszText = szName; + } + + + if (0 != (ifc_omserviceeditor::modifiedIcon & modifiedFlags)) + { + ifc_mlnavigationhelper *navHelper; + if (SUCCEEDED(OMUTILITY->GetMlNavigationHelper(Plugin_GetLibrary(), &navHelper))) + { + INT iImage; + WCHAR szIcon[1024] = {0}; + if (FAILED(service->GetIcon(szIcon, ARRAYSIZE(szIcon))) || + FAILED(navHelper->QueryIndex(szIcon, &iImage, NULL))) + { + iImage = -1; + } + + if (itemInfo.iImage != iImage) + { + itemInfo.mask |= NIMF_IMAGE | NIMF_IMAGESEL; + itemInfo.iImage = iImage; + itemInfo.iSelectedImage = iImage; + } + + navHelper->Release(); + } + } + + if (0 != itemInfo.mask) + { + if (FALSE == MLNavItem_SetInfo(hLibrary, &itemInfo)) + return E_FAIL; + } + + NAVITEMINAVLIDATE invalidate; + invalidate.hItem = hItem; + invalidate.fErase = FALSE; + invalidate.prc = NULL; + MLNavItem_Invalidate(hLibrary, &invalidate); + + return S_OK; +} + +HNAVITEM Navigation::FindService(UINT serviceId, ifc_omservice **serviceOut) +{ + if (NULL == hRoot || NULL == hLibrary) + { + if (NULL != serviceOut) *serviceOut = NULL; + return NULL; + } + + WCHAR szBuffer[128] = {0}; + NAVITEM item = {0}; + item.cbSize = sizeof(item); + item.mask = NIMF_TEXTINVARIANT | NIMF_PARAM; + item.pszInvariant = szBuffer; + item.cchInvariantMax = ARRAYSIZE(szBuffer); + + item.hItem = hRoot; + + while (NULL != item.hItem) + { + if (FALSE != MLNavItem_GetInfo(hLibrary, &item) && + FALSE != Navigation_CheckInvariantName(item.pszInvariant)) + { + ifc_omservice *service = (ifc_omservice*)item.lParam; + if (NULL != service && serviceId == service->GetId()) + { + if (NULL != serviceOut) + { + *serviceOut = service; + service->AddRef(); + } + return item.hItem; + } + } + + item.hItem = (HNAVITEM)SENDMLIPC(hLibrary, + (item.hItem == hRoot) ? ML_IPC_NAVITEM_GETCHILD : ML_IPC_NAVITEM_GETNEXT, + (WPARAM)item.hItem); + + } + + if (NULL != serviceOut) *serviceOut = NULL; + return NULL; +} + +HRESULT Navigation::ShowService(UINT serviceId, LPCWSTR pszUrl) +{ + ifc_omservice *service; + HNAVITEM hItem = FindService(serviceId, &service); + if (NULL == hItem) return E_FAIL; + + HRESULT hr = SelectItemInt(hItem, serviceId, pszUrl); + service->Release(); + + return hr; +} + +HNAVITEM Navigation::CreateItem(ifc_omservice *service) +{ + if (NULL == hLibrary || NULL == hRoot) return NULL; + return CreateItemInt(hRoot, service); +} + +HRESULT Navigation::GenerateServiceName(LPWSTR pszBuffer, INT cchBufferMax) +{ + if (NULL == pszBuffer) return E_POINTER; + *pszBuffer = L'\0'; + + if (NULL == hLibrary || NULL == hRoot) return E_UNEXPECTED; + + if (FAILED(Plugin_CopyResString(pszBuffer, cchBufferMax, MAKEINTRESOURCE(IDS_USERSERVICE_NAME)))) + return E_UNEXPECTED; + + INT cchName = lstrlen(pszBuffer); + LPWSTR pszFormat = pszBuffer + cchName; + INT cchFormatMax = cchBufferMax - cchName; + + WCHAR szText[512] = {0}; + NAVITEM item = {0}; + + item.cbSize = sizeof(item); + item.mask = NIMF_TEXT; + item.pszText = szText; + item.cchTextMax = ARRAYSIZE(szText); + + BOOL fFound = TRUE; + + for(INT index = 1; FALSE != fFound; index++) + { + fFound = FALSE; + if (FAILED(StringCchPrintf(pszFormat, cchFormatMax, L" %d", index))) + { + pszFormat = L'\0'; + return E_FAIL; + } + + item.hItem = MLNavItem_GetChild(hLibrary, hRoot); + while(NULL != item.hItem) + { + if (FALSE != MLNavItem_GetInfo(hLibrary, &item) && + CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, item.pszText, -1, pszBuffer, -1)) + { + fFound = TRUE; + break; + } + item.hItem = MLNavItem_GetNext(hLibrary, item.hItem); + } + } + + return S_OK; +} + +HRESULT Navigation::CreateUserService(HNAVITEM *itemOut) +{ + HRESULT hr; + + if (NULL != itemOut) + *itemOut = NULL; + + if (NULL == hRoot) return E_FAIL; + + INT serviceId = 710; + while(NULL != FindService(serviceId, NULL)) serviceId++; + + WCHAR szName[256]; + if (FAILED(GenerateServiceName(szName, ARRAYSIZE(szName)))) + return E_FAIL; + + ifc_omservice *service; + hr = ServiceHelper_Create(serviceId, szName, NULL, L"about:blank", 0, TRUE, &service); + + if (SUCCEEDED(hr)) + { + HNAVITEM hItem = CreateItem(service); + if (NULL == hItem) + { + hr = E_FAIL; + } + else + { + if (NULL != itemOut) + *itemOut = hItem; + } + + service->Release(); + } + + return hr; +} + +HNAVITEM Navigation::CreateItemInt(HNAVITEM hParent, ifc_omservice *service) +{ + if (NULL == service) return NULL; + ServiceHelper_RegisterPreAuthorized(service); + + WCHAR szName[256] = {0}, szInvariant[64] = {0}; + if (FAILED(service->GetName(szName, ARRAYSIZE(szName)))) + return NULL; + + if (L'\0' == szName[0]) + WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWNNAME, szName, ARRAYSIZE(szName)); + + if (FAILED(StringCchPrintf(szInvariant, ARRAYSIZE(szInvariant), NAVITEM_PREFIX L"%u", service->GetId()))) + return NULL; + + NAVINSERTSTRUCT nis = {0}; + nis.hInsertAfter = NULL; + nis.hParent = hParent; + + INT iIcon = -1; + ifc_mlnavigationhelper *navHelper; + if (NULL != OMUTILITY && SUCCEEDED(OMUTILITY->GetMlNavigationHelper(Plugin_GetLibrary(), &navHelper))) + { + WCHAR szIcon[2048] = {0}; + if (FAILED(service->GetIcon(szIcon, ARRAYSIZE(szIcon))) || + FAILED(navHelper->QueryIndex(szIcon, &iIcon, NULL))) + { + iIcon = -1; + } + navHelper->Release(); + } + + nis.item.cbSize = sizeof(NAVITEM); + nis.item.mask = NIMF_TEXT | NIMF_STYLE | NIMF_TEXTINVARIANT | NIMF_PARAM | NIMF_IMAGE | NIMF_IMAGESEL; + + nis.item.id = 0; + nis.item.pszText = szName; + nis.item.pszInvariant = szInvariant; + nis.item.lParam = (LPARAM)service; + + nis.item.style = 0; + UINT serviceFlags; + if (FAILED(service->GetFlags(&serviceFlags))) + serviceFlags = 0; + + if (0 != (WDSVCF_ROOT & serviceFlags)) + { + nis.item.style |= (NIS_HASCHILDREN | NIS_ALLOWCHILDMOVE); + iIcon = -1; + } + else if (0 != (WDSVCF_SPECIAL & serviceFlags)) + nis.item.style |= NIS_ITALIC; + else + nis.item.style |= NIS_ALLOWEDIT; + + nis.item.styleMask = nis.item.style; + + nis.item.iImage = iIcon; + nis.item.iSelectedImage = iIcon; + + + HNAVITEM hItem = MLNavCtrl_InsertItem(hLibrary, &nis); + if (NULL != hItem) + { + WebDevServiceHost *serviceHost; + if (SUCCEEDED(WebDevServiceHost::GetCachedInstance(&serviceHost))) + { + ifc_omserviceeventmngr *eventManager; + if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEventMngr, (void**)&eventManager))) + { + eventManager->RegisterHandler(serviceHost); + eventManager->Release(); + } + + serviceHost->Release(); + } + + service->AddRef(); + } + + return hItem; +} + +HRESULT Navigation::SelectItemInt(HNAVITEM hItem, UINT serviceId, LPCWSTR pszUrl) +{ + if (NULL == hLibrary) return E_UNEXPECTED; + + if (NULL != pszUrl && L'\0' != *pszUrl) + { + HRESULT hr = ForceUrl_Set(serviceId, pszUrl); + if (FAILED(hr)) return hr; + } + else + { + ForceUrl_Remove(); + } + + if (FALSE == MLNavItem_Select(hLibrary, hItem)) + { + ForceUrl_Remove(); + return E_FAIL; + } + + return S_OK; + +} +HNAVITEM Navigation::GetMessageItem(INT msg, INT_PTR param1) +{ + return (msg < ML_MSG_NAVIGATION_FIRST) ? + MLNavCtrl_FindItemById(hLibrary, param1) : + (HNAVITEM)param1; +} + +HRESULT Navigation::OnCreateView(HNAVITEM hItem, HWND hParent, HWND *hView) +{ + if (NULL == hView) return E_POINTER; + *hView = NULL; + + if (NULL == hLibrary) return E_UNEXPECTED; + if (NULL == hItem || NULL == hParent) return E_INVALIDARG; + + HRESULT hr; + + ifc_omservice *service; + hr = GetService(hItem, &service); + if (SUCCEEDED(hr)) + { + if (NULL == OMBROWSERMNGR) + hr = E_UNEXPECTED; + + if (SUCCEEDED(hr)) + { + hr = OMBROWSERMNGR->Initialize(NULL, Plugin_GetWinamp()); + if (SUCCEEDED(hr)) + { + LPCWSTR forceUrl; + if (FAILED(ForceUrl_Get(service->GetId(), &forceUrl))) + forceUrl = NULL; + + hr = OMBROWSERMNGR->CreateView(service, hParent, forceUrl, 0, hView); + + ForceUrl_Remove(); + } + } + + service->Release(); + } + return hr; +} + +HRESULT Navigation::OnContextMenu(HNAVITEM hItem, HWND hHost, POINTS pts) +{ + if (NULL == hItem || NULL == hHost) + return E_INVALIDARG; + + HWND hLibrary = Plugin_GetLibrary(); + if (NULL == hLibrary) return E_UNEXPECTED; + + HRESULT hr; + ifc_omservice *service; + hr = GetService(hItem, &service); + if (FAILED(hr)) return hr; + + POINT pt; + POINTSTOPOINT(pt, pts); + if (-1 == pt.x || -1 == pt.y) + { + NAVITEMGETRECT itemRect; + itemRect.fItem = FALSE; + itemRect.hItem = hItem; + if (MLNavItem_GetRect(hLibrary, &itemRect)) + { + MapWindowPoints(hHost, HWND_DESKTOP, (POINT*)&itemRect.rc, 2); + pt.x = itemRect.rc.left + 2; + pt.y = itemRect.rc.top + 2; + } + } + + HMENU hMenu = Menu_GetMenu(MENU_SERVICECONTEXT, service); + if (NULL != hMenu) + { + INT commandId = Menu_TrackPopup(Plugin_GetLibrary(), hMenu, + TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD, + pt.x, pt.y, hHost, NULL); + Menu_ReleaseMenu(hMenu, MENU_SERVICECONTEXT); + CommandManager_Process(hItem, service, commandId); + } + + service->Release(); + + return hr; +} + +HRESULT Navigation::OnEndTitleEdit(HNAVITEM hItem, LPCWSTR pszNewTitle) +{ + if (NULL == hItem) return E_INVALIDARG; + if (NULL == hLibrary) return E_UNEXPECTED; + + HRESULT hr; + + ifc_omservice *service; + hr = GetService(hItem, &service); + if (SUCCEEDED(hr)) + { + if (NULL != pszNewTitle) + { + ifc_omserviceeditor *editor; + hr = service->QueryInterface(IFC_OmServiceEditor, (void**)&editor); + if (SUCCEEDED(hr)) + { + hr = editor->SetName(pszNewTitle, FALSE); + editor->Release(); + } + } + + if (SUCCEEDED(hr)) + ServiceHelper_Save(service); + + service->Release(); + } + return hr; +} + +HRESULT Navigation::OnDeleteItem(HNAVITEM hItem) +{ + if (NULL == hItem) return E_INVALIDARG; + if (NULL == hLibrary) return E_UNEXPECTED; + + WCHAR szBuffer[2048] = {0}; + NAVITEM itemInfo = {0}; + + itemInfo.cbSize = sizeof(itemInfo); + itemInfo.hItem = hItem; + itemInfo.pszInvariant = szBuffer; + itemInfo.cchInvariantMax = ARRAYSIZE(szBuffer); + itemInfo.mask = NIMF_PARAM | NIMF_TEXTINVARIANT | NIMF_IMAGE; + + if (FALSE == MLNavItem_GetInfo(hLibrary, &itemInfo)) + return E_FAIL; + if (FALSE == Navigation_CheckInvariantName(szBuffer)) + return E_NAVITEM_UNKNOWN; + + ifc_omservice *service = (ifc_omservice*)itemInfo.lParam; + + if (NULL != service) + { + if (SUCCEEDED(service->GetIcon(szBuffer, ARRAYSIZE(szBuffer)))) + { + ifc_mlnavigationhelper *navHelper; + if (SUCCEEDED(OMUTILITY->GetMlNavigationHelper(Plugin_GetLibrary(), &navHelper))) + { + navHelper->ReleaseIndex(szBuffer); + navHelper->Release(); + } + } + + ifc_ombrowserwndmngr *windowManager; + if (NULL != OMBROWSERMNGR && SUCCEEDED(OMBROWSERMNGR->QueryInterface(IFC_OmBrowserWindowManager, (void**)&windowManager))) + { + UINT serviceId = service->GetId(); + + ifc_ombrowserwndenum *windowEnum; + if (SUCCEEDED(windowManager->Enumerate(NULL, &serviceId, &windowEnum))) + { + HWND hwnd; + while (S_OK == windowEnum->Next(1, &hwnd, NULL)) + { + DestroyWindow(hwnd); + } + windowEnum->Release(); + } + + windowManager->Release(); + } + + WebDevServiceHost *serviceHost; + if (SUCCEEDED(WebDevServiceHost::GetCachedInstance(&serviceHost))) + { + ifc_omserviceeventmngr *eventManager; + if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEventMngr, (void**)&eventManager))) + { + eventManager->UnregisterHandler(serviceHost); + eventManager->Release(); + } + serviceHost->Release(); + } + + itemInfo.mask = NIMF_PARAM; + itemInfo.lParam = 0L; + MLNavItem_SetInfo(hLibrary, &itemInfo); + + service->Release(); + } + + + + return S_OK; +} + +HRESULT Navigation::OnKeyDown(HNAVITEM hItem, NMTVKEYDOWN *pnmkd) +{ + if (NULL == hItem) return E_INVALIDARG; + if (NULL == hLibrary) return E_UNEXPECTED; + + ifc_omservice *service; + HRESULT hr = GetService(hItem, &service); + if (SUCCEEDED(hr)) + { + switch(pnmkd->wVKey) + { + case VK_DELETE: + Command_DeleteItem(hItem); + break; + } + + service->Release(); + } + return hr; +} + +HRESULT Navigation::OnControlDestroy() +{ + SaveOrder(); + return S_OK; +} + +#define CBCLASS Navigation +START_DISPATCH; +CB(ADDREF, AddRef) +CB(RELEASE, Release) +CB(QUERYINTERFACE, QueryInterface) +VCB(API_IMAGECHANGED, ImageChanged) +END_DISPATCH; +#undef CBCLASS \ No newline at end of file -- cgit