aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/menuv5.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/menuv5.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Winamp/menuv5.cpp')
-rw-r--r--Src/Winamp/menuv5.cpp653
1 files changed, 653 insertions, 0 deletions
diff --git a/Src/Winamp/menuv5.cpp b/Src/Winamp/menuv5.cpp
new file mode 100644
index 00000000..350548d4
--- /dev/null
+++ b/Src/Winamp/menuv5.cpp
@@ -0,0 +1,653 @@
+/** (c) Nullsoft, Inc. C O N F I D E N T I A L
+ ** Filename:
+ ** Project:
+ ** Description:
+ ** Author:
+ ** Created:
+ **/
+
+#include "main.h"
+#include "menuv5.h"
+#include "../nu/AutoWide.h"
+#include "../Plugins/General/gen_ml/ml.h"
+
+#define TREE_LOCALMEDIA 1000
+#define TREE_PLAYLISTS 3001
+#define TREE_DEVICES 10000
+#define TREE_QUERIES 1000
+
+extern HINSTANCE language_pack_instance;
+
+
+void ensureInScreen(HMENU menu, int *x, int *y, int *flag, int width, int height);
+
+HMENU v5_top_menu = NULL;
+
+
+int MergeMenu(HMENU pMenuDestination, const HMENU pMenuAdd, int bTopLevel /*=false*/)
+{
+ // Abstract:
+ // Merges two menus.
+ //
+ // Parameters:
+ // pMenuDestination - [in, retval] destination menu handle
+ // pMenuAdd - [in] menu to merge
+ // bTopLevel - [in] indicator for special top level behavior
+ //
+ // Return value:
+ // <false> in case of error.
+ //
+ // Comments:
+ // This function calles itself recursivley. If bTopLevel is set to true,
+ // we append popups at top level or we insert before <Window> or <Help>.
+
+ // get the number menu items in the menus
+ int iMenuAddItemCount = GetMenuItemCount(pMenuAdd);
+ int iMenuDestItemCount = GetMenuItemCount(pMenuDestination);
+ int iLoop;
+
+ // if there are no items return
+ if( iMenuAddItemCount == 0 )
+ return 1;
+
+ // if we are not at top level and the destination menu is not empty
+ // -> we append a seperator
+ if( !bTopLevel && iMenuDestItemCount > 0 )
+ AppendMenu(pMenuDestination, MF_SEPARATOR, 0, 0);
+
+ // iterate through the top level of
+ for( iLoop = 0; iLoop < iMenuAddItemCount; iLoop++ )
+ {
+ HMENU pSubMenu = 0;
+ // get the menu string from the add menu
+ wchar_t sMenuAddString[1024] = {0}; // hope it's enough
+
+ GetMenuStringW(pMenuAdd, iLoop, sMenuAddString, 1024, MF_BYPOSITION);
+
+ // try to get the submenu of the current menu item
+ pSubMenu =GetSubMenu(pMenuAdd, iLoop);
+
+ // check if we have a sub menu
+ if (!pSubMenu)
+ {
+ // normal menu item
+ // read the source and append at the destination
+ UINT nState = GetMenuState(pMenuAdd, iLoop, MF_BYPOSITION);
+ UINT nItemID = GetMenuItemID(pMenuAdd, iLoop);
+
+ if(AppendMenuW(pMenuDestination, nState, nItemID, sMenuAddString))
+ {
+ // menu item added, don't forget to correct the item count
+ iMenuDestItemCount++;
+ }
+ else
+ {
+ // MergeMenu: AppendMenu failed!
+ return 0;
+ }
+ }
+ else
+ {
+ HMENU NewPopupMenu=NULL;
+ // create or insert a new popup menu item
+
+ // default insert pos is like ap
+ int iInsertPosDefault = -1;
+
+ // if we are at top level merge into existing popups rather than
+ // creating new ones
+ if( bTopLevel )
+ {
+ //ASSERT( sMenuAddString != "&?" && sMenuAddString != "?" );
+ //CString sAdd( sMenuAddString );
+ //sAdd.Remove('&'); // for comparison of menu items supress '&'
+ int bAdded = 0;
+ int iLoop1=0;
+
+ // try to find existing popup
+ for( iLoop1 = 0; iLoop1 < iMenuDestItemCount; iLoop1++ )
+ {
+ // get the menu string from the destination menu
+ wchar_t sDest[1024] = {0}; // hope it's enough
+ GetMenuStringW(pMenuDestination, iLoop1, sDest, 1024, MF_BYPOSITION );
+ //sDest.Remove( '&' ); // for a better compare (s.a.)
+
+ //if( !lstrcmp(sAdd,sDest))
+ {
+ // we got a hit -> merge the two popups
+ // try to get the submenu of the desired destination menu item
+ HMENU pSubMenuDest = GetSubMenu(pMenuDestination, iLoop1 );
+
+ if( pSubMenuDest )
+ {
+ // merge the popup recursivly and continue with outer for loop
+ if( !MergeMenu( pSubMenuDest, pSubMenu, 0 ))
+ return 0;
+
+ bAdded = 1;
+ break;
+ }
+ }
+
+ // alternativ insert before <Window> or <Help>
+ //if( iInsertPosDefault == -1 && ( sDest == "Window" || sDest == "?" || sDest == "Help" ))
+ // iInsertPosDefault = iLoop1;
+
+ }
+
+ if( bAdded )
+ {
+ // menu added, so go on with loop over pMenuAdd's top level
+ continue;
+ }
+ }
+
+ // if the top level search did not find a position append the menu
+ if( iInsertPosDefault == -1 )
+ iInsertPosDefault = GetMenuItemCount(pMenuDestination);
+
+ // create a new popup and insert before <Window> or <Help>
+ NewPopupMenu = CreatePopupMenu();
+ if( !NewPopupMenu)
+ {
+ // MergeMenu: CreatePopupMenu failed!
+ return 0;
+ }
+
+ // merge the new popup recursivly
+ if( !MergeMenu( NewPopupMenu, pSubMenu, 0 ))
+ return 0;
+
+ // insert the new popup menu into the destination menu
+ HMENU hNewMenu = NewPopupMenu;
+ {
+ MENUITEMINFOW menuItem={sizeof(MENUITEMINFO),
+ MIIM_TYPE|MIIM_SUBMENU,
+ MFT_STRING,
+ MFS_ENABLED,
+ 0, //wID
+ hNewMenu, // hSubMenu
+ NULL, // hbmpChecked
+ NULL, // hbmpUnchecked
+ 0, // dwItemData
+ sMenuAddString, // dwTypeData
+ 0, // cch
+ };
+
+ if (InsertMenuItemW(pMenuDestination, iInsertPosDefault, TRUE, &menuItem))
+ {
+ // don't forget to correct the item count
+ iMenuDestItemCount++;
+ }
+ else
+ {
+ // MergeMenu: InsertMenu failed!
+ return 0;
+ }
+ }
+
+ }
+ }
+
+ return 1;
+}
+
+int getMenuItemPos(HMENU menu, UINT command)
+{
+ int i;
+ for (i = 0;i < 256;i++)
+ {
+ MENUITEMINFO mii = {sizeof(mii), MIIM_ID, };
+ if (!GetMenuItemInfo(menu, i, TRUE, &mii)) break;
+ if (mii.wID == command) return i;
+ }
+ return -1;
+}
+
+extern int g_SkinTop, g_BookmarkTop;
+
+int V5_File_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ int flag = TPM_LEFTALIGN;
+ HMENU file_menu = GetSubMenu(v5_top_menu, 0);
+ HMENU hMenu = GetSubMenu(file_menu, 3);
+ MENUITEMINFOW i = {sizeof(i), };
+ FILE *fp;
+ int a = 34768;
+ int offs = 3;
+ int count = GetMenuItemCount(hMenu) + 1;
+
+ i.fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID;
+ i.fType = MFT_STRING;
+ i.wID = 34768;
+
+ // remove all of the items we might have added - do by command for certainty
+ while (count){
+ if(!RemoveMenu(hMenu, a++, MF_BYCOMMAND)) break;
+ count--;
+ }
+
+ fp = _wfopen(BOOKMARKFILE8, L"rt");
+ if (fp)
+ {
+ while (1)
+ {
+ char ft[FILETITLE_SIZE] = {0}, fn[FILENAME_SIZE] = {0};
+ fgets(fn, FILENAME_SIZE, fp);
+ if (feof(fp)) break;
+ fgets(ft, FILETITLE_SIZE, fp);
+ if (feof(fp)) break;
+ if (ft[0] && fn[0])
+ {
+ if (fn[lstrlenA(fn) - 1] == '\n') fn[lstrlenA(fn) - 1] = 0;
+ if (ft[lstrlenA(ft) - 1] == '\n') ft[lstrlenA(ft) - 1] = 0;
+ if (ft[0] && fn[0])
+ {
+ i.dwTypeData = AutoWideDup(ft, CP_UTF8);
+ i.cch = lstrlenW(i.dwTypeData);
+ RemoveMenu(hMenu, i.wID, MF_BYCOMMAND);
+ InsertMenuItemW(hMenu, i.wID + offs - 34768, TRUE, &i);
+ i.wID++;
+ }
+ }
+ }
+ fclose(fp);
+ }
+ g_BookmarkTop = i.wID;
+
+ // put in a place holder item if there were no read bookmarks
+ if (g_BookmarkTop == 34768)
+ {
+ i.dwTypeData = getStringW(IDS_NO_BOOKMARKS,NULL,0);
+ i.cch = lstrlenW(i.dwTypeData);
+ InsertMenuItemW(hMenu, i.wID + offs - 34768, TRUE, &i);
+ EnableMenuItem(hMenu, i.wID, MF_BYCOMMAND | MF_GRAYED);
+ }
+
+ ensureInScreen(file_menu, &x, &y, &flag, width, height);
+
+ DoTrackPopup(file_menu, flag, x, y, hwnd);
+ return 1;
+}
+
+int V5_Play_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ HMENU play_menu = GetSubMenu(v5_top_menu, 1);
+ int flag = TPM_LEFTALIGN;
+ ensureInScreen(play_menu, &x, &y, &flag, width, height);
+ DoTrackPopup(play_menu, flag, x, y, hwnd);
+ return 1;
+}
+
+
+int V5_Options_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ int flag = TPM_LEFTALIGN;
+ HMENU options_menu = GetSubMenu(v5_top_menu, 2);
+ HMENU eqMenu = NULL;
+
+ { // set options skin menu to the skin menu
+ extern HMENU g_submenus_skins1;
+ MENUITEMINFO mi = {sizeof(mi), MIIM_SUBMENU};
+ mi.hSubMenu = g_submenus_skins1;
+ SetMenuItemInfoW(options_menu, 0, TRUE, &mi);
+ }
+
+ eqMenu = GetSubMenu(options_menu, 2);
+ CheckMenuItem(eqMenu, EQ_ENABLE, config_use_eq ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(options_menu, WINAMP_OPTIONS_DSIZE, config_dsize ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(options_menu, WINAMP_OPTIONS_AOT, config_aot ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(options_menu, WINAMP_OPTIONS_ELAPSED, config_timeleftmode ? MF_UNCHECKED : MF_CHECKED);
+ CheckMenuItem(options_menu, WINAMP_OPTIONS_REMAINING, config_timeleftmode ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(options_menu, WINAMP_OPTIONS_PREFS, IsWindow(prefs_hwnd) ? MF_CHECKED : MF_UNCHECKED);
+ ensureInScreen(options_menu, &x, &y, &flag, width, height);
+ DoTrackPopup(options_menu, flag, x, y, hwnd);
+ return 1;
+}
+
+int V5_Windows_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ HMENU windows_menu = GetSubMenu(v5_top_menu, 3);
+ int flag = TPM_LEFTALIGN;
+ CheckMenuItem(windows_menu, WINAMP_OPTIONS_PLEDIT, config_pe_open ? MF_CHECKED : MF_UNCHECKED);
+ CheckMenuItem(windows_menu, WINAMP_VISPLUGIN, vis_running() ? MF_CHECKED : MF_UNCHECKED);
+ if (g_has_video_plugin) CheckMenuItem(windows_menu, WINAMP_OPTIONS_VIDEO, config_video_open ? MF_CHECKED : MF_UNCHECKED);
+ ensureInScreen(windows_menu, &x, &y, &flag, width, height);
+ DoTrackPopup(windows_menu, flag, x, y, hwnd);
+ return 1;
+}
+
+int Help_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ HMENU help_menu = GetSubMenu(v5_top_menu, 4);
+ int flag = TPM_LEFTALIGN;
+
+ MENUITEMINFOW i = {sizeof(i), };
+ i.fMask = MIIM_TYPE;
+ i.fType = MFT_STRING;
+ i.dwTypeData = getStringW(IDS_WINAMP_MENUITEM, NULL, 0);
+ i.cch = (UINT)wcslen(i.dwTypeData);
+ SetMenuItemInfoW(help_menu, WINAMP_HELP_ABOUT, FALSE, &i);
+
+ ensureInScreen(help_menu, &x, &y, &flag, width, height);
+ DoTrackPopup(help_menu, flag, x, y, hwnd);
+ return 1;
+}
+
+int V5_Help_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ return Help_Menu(hwnd, x, y, width, height);
+}
+
+LRESULT sendMlIpc(int msg, WPARAM param);
+
+// TODO:: need to make this only show what's needed at the time ie it'll still show even if there's no ml_playlists
+// and properly show if there's no playlists
+int V5_PE_File_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ int flag = TPM_LEFTALIGN;
+ HMENU pefile_menu = GetSubMenu(v5_top_menu, 5);
+ HMENU playlistsmenu = NULL;
+ HMENU viewmenu = NULL;
+ HWND mlwnd = (HWND)sendMlIpc(0, 0);
+ int viewmenu_added = 0;
+ g_open_ml_item_in_pe = 1;
+ if (mlwnd)
+ {
+ mlGetTreeStruct mgts = { TREE_PLAYLISTS, 45000, -1 };
+ playlistsmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (WPARAM) & mgts, ML_IPC_GETTREE);
+ if (playlistsmenu)
+ {
+ mlGetTreeStruct mgts = { TREE_QUERIES, 45000, -1 };
+ viewmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (WPARAM) & mgts, ML_IPC_GETTREE);
+ if (GetMenuItemCount(playlistsmenu) == 0) InsertMenuW(playlistsmenu, 0, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, getStringW(IDS_ML_NO_PLAYLISTS,NULL,0));
+ InsertMenuW(pefile_menu, 2, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT_PTR)playlistsmenu, getStringW(IDS_ML_OPEN_PLAYLIST,NULL,0));
+ if (viewmenu && GetMenuItemCount(viewmenu) > 0)
+ {
+ viewmenu_added = 1;
+ InsertMenuW(pefile_menu, 3, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT_PTR)viewmenu, getStringW(IDS_ML_OPEN_VIEW_RESULTS,NULL,0));
+ }
+ }
+ }
+
+ ModifyMenuW(pefile_menu, ID_PE_CLOSE, MF_BYCOMMAND | MF_STRING, ID_PE_CLOSE, config_pe_open ? getStringW(IDS_PE_CLOSE,NULL,0) : getStringW(IDS_PE_OPEN,NULL,0));
+ ensureInScreen(pefile_menu, &x, &y, &flag, width, height);
+ DoTrackPopup(pefile_menu, flag, x, y, hwnd);
+
+ if (playlistsmenu)
+ {
+ if (viewmenu_added) RemoveMenu(pefile_menu, 3, MF_BYPOSITION);
+ if (viewmenu) DestroyMenu(viewmenu);
+ RemoveMenu(pefile_menu, 2, MF_BYPOSITION);
+ DestroyMenu(playlistsmenu);
+ }
+ return 1;
+}
+
+int V5_PE_Playlist_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ HMENU peplaylist_menu = GetSubMenu(v5_top_menu, 6);
+ int flag = TPM_LEFTALIGN;
+ ensureInScreen(peplaylist_menu, &x, &y, &flag, width, height);
+ DoTrackPopup(peplaylist_menu, flag, x, y, hwnd);
+ return 1;
+}
+
+int V5_PE_Sort_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ HMENU pesort_menu = GetSubMenu(v5_top_menu, 7);
+ int flag = TPM_LEFTALIGN;
+ ensureInScreen(pesort_menu, &x, &y, &flag, width, height);
+ DoTrackPopup(pesort_menu, flag, x, y, hwnd);
+ return 1;
+}
+
+int V5_PE_Help_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ return Help_Menu(hwnd, x, y, width, height);
+}
+
+int V5_ML_File_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ int flag = TPM_LEFTALIGN;
+ HMENU mlfile_menu = GetSubMenu(v5_top_menu, 8);
+ HWND mlwnd = (HWND)sendMlIpc(0, 0);
+ HWND mlplwnd = (HWND)SendMessageW(mlwnd, WM_ML_IPC, 0, ML_IPC_GETPLAYLISTWND);
+ ModifyMenuW(mlfile_menu, 3, MF_BYPOSITION | (mlplwnd == NULL ? MF_GRAYED : 0), ID_MLFILE_SAVEPLAYLIST, getStringW(IDS_ML_EXPORT_PLAYLIST,NULL,0));
+ {
+ int visible = IsWindowVisible(mlwnd);
+ int p = getMenuItemPos(mlfile_menu, ID_FILE_CLOSELIBRARY);
+ if (p == -1) p = getMenuItemPos(mlfile_menu, ID_FILE_SHOWLIBRARY);
+ ModifyMenuW(mlfile_menu, p, MF_BYPOSITION | MF_STRING, visible ? ID_FILE_CLOSELIBRARY : ID_FILE_SHOWLIBRARY, visible ? getStringW(IDS_ML_CLOSE_ML,NULL,0) : getStringW(IDS_ML_OPEN_ML,NULL,0));
+ }
+ ensureInScreen(mlfile_menu, &x, &y, &flag, width, height);
+ DoTrackPopup(mlfile_menu, flag, x, y, hwnd);
+ return 1;
+}
+
+int V5_ML_View_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ int flag = TPM_LEFTALIGN;
+ HMENU mlview_menu = GetSubMenu(v5_top_menu, 9), mediamenu = NULL;
+ HWND mlwnd = (HWND)sendMlIpc(0, 0);
+ if (mlwnd)
+ {
+ mlGetTreeStruct mgts = { 0, 45000, -1 };
+ mediamenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (WPARAM) & mgts, ML_IPC_GETTREE);
+ if (mediamenu)
+ {
+ MergeMenu(mediamenu, mlview_menu, 0);
+ //InsertMenu(mediamenu, 0, MF_BYPOSITION | MF_STRING, ID_MLVIEW_MEDIA, "All &Media");
+ //InsertMenu(mlview_menu, 1, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT)mediamenu, "&Local Media");
+ }/*
+ mgts.item_start = TREE_PLAYLISTS;
+ playlistsmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (int) & mgts, ML_IPC_GETTREE);
+ if (playlistsmenu)
+ {
+ if (GetMenuItemCount(playlistsmenu) == 0) InsertMenu(playlistsmenu, 0, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, "No playlists");
+ InsertMenu(mlview_menu, 2, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT)playlistsmenu, "&Playlists");
+ }
+ mgts.item_start = TREE_DEVICES;
+ devicesmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (int) & mgts, ML_IPC_GETTREE);
+ if (devicesmenu)
+ {
+ if (GetMenuItemCount(devicesmenu) == 0) InsertMenu(devicesmenu, 0, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, "No devices");
+ InsertMenu(mlview_menu, 3, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT)devicesmenu, "&Devices");
+ }*/
+ }
+
+ g_open_ml_item_in_pe = 0;
+
+ //ID_MLVIEW_PLAYLISTS
+ //ID_MLVIEW_DEVICES
+
+ ensureInScreen(mediamenu, &x, &y, &flag, width, height);
+ DoTrackPopup(mediamenu, flag, x, y, hwnd);
+/*
+ if (devicesmenu)
+ {
+ RemoveMenu(mlview_menu, 3, MF_BYPOSITION);
+ DestroyMenu(devicesmenu);
+ }
+ if (playlistsmenu)
+ {
+ RemoveMenu(mlview_menu, 2, MF_BYPOSITION);
+ DestroyMenu(playlistsmenu);
+ }*/
+ if (mediamenu)
+ {
+ //RemoveMenu(mlview_menu, 1, MF_BYPOSITION);
+ DestroyMenu(mediamenu);
+ }
+ return 1;
+}
+
+int V5_ML_Help_Menu(HWND hwnd, int x, int y, int width, int height)
+{
+ return Help_Menu(hwnd, x, y, width, height);
+}
+
+int V5_PE_ListOfPlaylists_Menu(int x, int y)
+{
+ HMENU viewmenu = NULL;
+ mlGetTreeStruct mgts = { TREE_PLAYLISTS, 55000, -1 };
+ HWND mlwnd = (HWND)sendMlIpc(0, 0);
+ HMENU playlistsmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (WPARAM) & mgts, ML_IPC_GETTREE);
+ if (playlistsmenu)
+ {
+ InsertMenuW(playlistsmenu, 0, MF_BYPOSITION | MF_STRING, ID_MANAGEPLAYLISTS, getStringW(IDS_ML_MANAGE_PLAYLISTS,NULL,0));
+ {
+ mlGetTreeStruct mgts = { TREE_QUERIES, 55000, -1 };
+ viewmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (WPARAM) &mgts, ML_IPC_GETTREE);
+ }
+ if (viewmenu && GetMenuItemCount(viewmenu) > 0)
+ InsertMenuW(playlistsmenu, 1, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT_PTR)viewmenu, getStringW(IDS_ML_SMART_VIEW_RESULTS,NULL,0));
+ InsertMenu(playlistsmenu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
+ g_open_ml_item_in_pe = 1;
+ DoTrackPopup(playlistsmenu, TPM_LEFTALIGN, x, y, hMainWindow);
+ }
+ DestroyMenu(playlistsmenu);
+ DestroyMenu(viewmenu);
+ return 1;
+}
+
+void getViewportFromPoint(POINT *pt, RECT *r)
+{
+ if (!r || !pt) return ;
+ {
+
+ HMONITOR hm;
+ hm = MonitorFromPoint(*pt, MONITOR_DEFAULTTONULL);
+ if (hm)
+ {
+ MONITORINFOEXW mi;
+ memset(&mi, 0, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+
+ if (GetMonitorInfo(hm, &mi))
+ {
+ *r = mi.rcMonitor;
+ return ;
+ }
+ }
+ }
+}
+
+#undef GetSystemMetrics
+
+void ensureInScreen(HMENU menu, int *x, int *y, int *flag, int width, int height)
+{
+ POINT pt = {*x, *y};
+ int nitems = GetMenuItemCount(menu);
+ int i;
+ RECT mwr;
+ RECT monitor;
+ int rightdone = 0;
+ int bottomdone = 0;
+ int xedge = GetSystemMetrics(SM_CXEDGE);
+ int yedge = GetSystemMetrics(SM_CYEDGE);
+ int itemheight = GetSystemMetrics(SM_CYMENU);
+ int checkmarkwidth = GetSystemMetrics(SM_CXMENUCHECK);
+ int cury = *y + yedge + 1;
+ GetWindowRect(hMainWindow, &mwr);
+ getViewportFromPoint(&pt, &monitor);
+ /*if (nitems*GetSystemMetrics(SM_CYMENU)+yedge*2+*y > monitor.bottom) {
+ bottomdone = 1;
+ *y -= height;
+ *flag &= ~TPM_TOPALIGN;
+ *flag |= TPM_BOTTOMALIGN;
+ }*/
+ for (i = 0;i < nitems;i++)
+ {
+ SIZE s={0};
+ RECT item;
+ MENUITEMINFOW info = {sizeof(info), MIIM_DATA | MIIM_TYPE | MIIM_STATE | MIIM_ID, MFT_STRING, };
+ GetMenuItemRect(hMainWindow, menu, i, &item);
+ item.left -= mwr.left;
+ item.top -= mwr.top;
+ item.right -= mwr.left;
+ item.bottom -= mwr.top;
+ if (item.top == 0 && item.left == 0)
+ {
+ // item has never been shown so MS wont give us the rect, I HATE THEM ! I HATE THEM SO MUCH ARRRG !
+
+ // y
+ item.top = cury;
+ {
+ GetMenuItemInfoW(menu, i, TRUE, &info);
+ if (info.fType & MFT_SEPARATOR)
+ cury += (itemheight - 1) >> 1;
+ else
+ {
+ cury += itemheight - 2;
+ //info.dwTypeData = (LPTSTR) MALLOC(++info.cch + 1);
+ GetMenuItemInfoW(menu, i, TRUE, &info);
+ //info.dwTypeData[info.cch] = 0;
+ }
+ }
+ item.bottom = cury;
+
+ // x
+ if (info.dwTypeData)
+ {
+ LOGFONT m_lf;
+ HFONT font = nullptr;
+ HDC dc = nullptr;
+ NONCLIENTMETRICS nm = {sizeof (NONCLIENTMETRICS), };
+ memset((PVOID) &m_lf, 0, sizeof (LOGFONT));
+ SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, nm.cbSize, &nm, 0);
+ m_lf = nm.lfMenuFont;
+ font = CreateFontIndirectW(&m_lf);
+ dc = GetDC(hMainWindow);
+ GetTextExtentPoint32(dc, info.dwTypeData, lstrlen(info.dwTypeData), &s);
+ ReleaseDC(hMainWindow, dc);
+ DeleteObject(font);
+ //free(info.dwTypeData);
+ }
+ if (!(info.fType & MFT_SEPARATOR))
+ {
+ item.left = *x + xedge + 1;
+ item.right = item.left + s.cx + checkmarkwidth * 2 + xedge + 1;
+ }
+ else
+ {
+ item.left = *x + xedge + 1;
+ item.right = item.left + xedge + 1;
+ }
+ }
+ else
+ {
+ item.left += *x;
+ item.top += *y;
+ item.right += *x;
+ item.bottom += *y;
+ item.right += xedge * 2 + 2; // to avoid last test
+ cury = item.bottom;
+ }
+ if (!bottomdone && cury > monitor.bottom)
+ {
+ bottomdone = 1;
+ *y -= height;
+ *flag &= ~TPM_TOPALIGN;
+ *flag |= TPM_BOTTOMALIGN;
+ }
+ if (!rightdone && item.right > monitor.right)
+ {
+ rightdone = 1;
+ *x += width;
+ *flag &= ~TPM_LEFTALIGN;
+ *flag |= TPM_RIGHTALIGN;
+ }
+ if (rightdone && bottomdone) return ;
+ }
+ cury += yedge + 1;
+ if (!bottomdone && cury > monitor.bottom)
+ {
+ //bottomdone = 1;
+ *y -= height;
+ *flag &= ~TPM_TOPALIGN;
+ *flag |= TPM_BOTTOMALIGN;
+ }
+}
+
+