menuactions.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. #include "precomp__gen_ff.h"
  2. #include "menuactions.h"
  3. #include "wa2frontend.h"
  4. #include <api/skin/skinparse.h>
  5. #include "wa2cfgitems.h"
  6. #include "main.h"
  7. #include "resource.h"
  8. #include <api/locales/xlatstr.h>
  9. #include "../gen_ml/ml_ipc.h"
  10. #include "../winamp/gen.h"
  11. #include "../Agave/Language/api_language.h"
  12. #include "../gen_ml/menufucker.h"
  13. #include "../Winamp/strutil.h"
  14. extern librarySendToMenuStruct mainSendTo;
  15. #define WINAMP_OPTIONS_DSIZE 40165
  16. extern void addWindowOptionsToContextMenu(ifc_window *w);
  17. extern void removeWindowOptionsFromContextMenu();
  18. extern ifc_window *g_controlMenuTarget;
  19. extern HMENU controlmenu;
  20. int lowest_itempos = 0;
  21. int highest_itempos = -1;
  22. int lowest_witempos = 0;
  23. int lowest_witempos2 = 0;
  24. int highest_witempos = -1;
  25. int highest_witempos2 = -1;
  26. int optionsmenu_wa = 1;
  27. TList<HMENU> menulist;
  28. TList<HMENU> wmenulist;
  29. int in_menu = 0;
  30. //-----------------------------------------------------------------------------------------------
  31. MenuActions::MenuActions()
  32. {
  33. registerAction(L"menu", _ACTION_MENU);
  34. registerAction(L"sysmenu", _ACTION_SYSMENU);
  35. registerAction(L"controlmenu", _ACTION_CONTROLMENU);
  36. registerAction(L"MENU:WA5:File", ACTION_WA5FILEMENU);
  37. registerAction(L"MENU:WA5:Play", ACTION_WA5PLAYMENU);
  38. registerAction(L"MENU:WA5:Options", ACTION_WA5OPTIONSMENU);
  39. registerAction(L"MENU:WA5:Windows", ACTION_WA5WINDOWSMENU);
  40. registerAction(L"MENU:WA5:Help", ACTION_WA5HELPMENU);
  41. registerAction(L"MENU:WA5:PE_File", ACTION_WA5PEFILEMENU);
  42. registerAction(L"MENU:WA5:PE_Playlist", ACTION_WA5PEPLAYLISTMENU);
  43. registerAction(L"MENU:WA5:PE_Sort", ACTION_WA5PESORTMENU);
  44. registerAction(L"MENU:WA5:PE_Help", ACTION_WA5PEHELPMENU);
  45. registerAction(L"MENU:WA5:ML_File", ACTION_WA5MLFILEMENU);
  46. registerAction(L"MENU:WA5:ML_View", ACTION_WA5MLVIEWMENU);
  47. registerAction(L"MENU:WA5:ML_Help", ACTION_WA5MLHELPMENU);
  48. registerAction(L"PE_Add", ACTION_PEADD);
  49. registerAction(L"PE_Rem", ACTION_PEREM);
  50. registerAction(L"PE_Sel", ACTION_PESEL);
  51. registerAction(L"PE_Misc", ACTION_PEMISC);
  52. registerAction(L"PE_List", ACTION_PELIST);
  53. registerAction(L"PE_ListOfLists", ACTION_PELISTOFLISTS);
  54. registerAction(L"VID_FS", ACTION_VIDFS);
  55. registerAction(L"VID_1X", ACTION_VID1X);
  56. registerAction(L"VID_2X", ACTION_VID2X);
  57. registerAction(L"VID_TV", ACTION_VIDTV);
  58. registerAction(L"VID_Misc", ACTION_VIDMISC);
  59. registerAction(L"VIS_Next", ACTION_VISNEXT);
  60. registerAction(L"VIS_Prev", ACTION_VISPREV);
  61. registerAction(L"VIS_FS", ACTION_VISFS);
  62. registerAction(L"VIS_CFG", ACTION_VISCFG);
  63. registerAction(L"VIS_Menu", ACTION_VISMENU);
  64. registerAction(L"trackinfo", ACTION_TRACKINFO);
  65. registerAction(L"trackmenu", ACTION_TRACKMENU);
  66. registerAction(L"ML_SendTo", ACTION_SENDTO);
  67. }
  68. //-----------------------------------------------------------------------------------------------
  69. MenuActions::~MenuActions()
  70. {}
  71. static LRESULT sendMlIpc(int msg, WPARAM param) {
  72. static HWND mlwnd = NULL;
  73. if(!IsWindow(mlwnd)) {
  74. int IPC_GETMLWINDOW = (INT)SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"LibraryGetWnd", IPC_REGISTER_WINAMP_IPCMESSAGE);
  75. if(IPC_GETMLWINDOW > 65536) mlwnd = (HWND)SendMessageW(plugin.hwndParent,WM_WA_IPC,0,IPC_GETMLWINDOW);
  76. }
  77. if(!IsWindow(mlwnd)) return 0;
  78. return SendMessageW(mlwnd,WM_ML_IPC,param,msg);
  79. }
  80. //-----------------------------------------------------------------------------------------------
  81. int MenuActions::onActionId(int pvtid, const wchar_t *action, const wchar_t *param /* =NULL */, int p1 /* =0 */, int p2 /* =0 */, void *data /* =NULL */, int datalen /* =0 */, ifc_window *source /* =NULL */)
  82. {
  83. SetCursor(LoadCursor(NULL, IDC_ARROW));
  84. RECT r = {0, 0, 0, 0};
  85. if (source) source->getWindowRect(&r);
  86. int height = r.bottom - r.top;
  87. int width = r.right - r.left;
  88. in_menu = 1;
  89. switch (pvtid)
  90. {
  91. case _ACTION_MENU:
  92. {
  93. if (!_wcsicmp(param, L"presets"))
  94. {
  95. wa2.triggerEQPresetMenu(p1, p2);
  96. }
  97. }
  98. break;
  99. case _ACTION_SYSMENU:
  100. {
  101. addWindowOptionsToContextMenu(source);
  102. wa2.triggerPopupMenu(p1, p2);
  103. break;
  104. }
  105. case _ACTION_CONTROLMENU:
  106. {
  107. if (g_controlMenuTarget != NULL)
  108. removeWindowOptionsFromContextMenu();
  109. addWindowOptionsToContextMenu(g_controlMenuTarget);
  110. g_controlMenuTarget = source;
  111. HMENU ctrlmenu = GetSubMenu(controlmenu, 0);
  112. DoTrackPopup(ctrlmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, p1, p2, wa2.getMainWindow());
  113. break;
  114. }
  115. case ACTION_WA5FILEMENU:
  116. {
  117. wa2.triggerFileMenu(p1, p2, width, height);
  118. break;
  119. }
  120. case ACTION_WA5PLAYMENU:
  121. {
  122. wa2.triggerPlayMenu(p1, p2, width, height);
  123. break;
  124. }
  125. case ACTION_WA5OPTIONSMENU:
  126. {
  127. wa2.triggerOptionsMenu(p1, p2, width, height);
  128. break;
  129. }
  130. case ACTION_WA5WINDOWSMENU:
  131. {
  132. wa2.triggerWindowsMenu(p1, p2, width, height);
  133. break;
  134. }
  135. case ACTION_WA5HELPMENU:
  136. {
  137. wa2.triggerHelpMenu(p1, p2, width, height);
  138. break;
  139. }
  140. case ACTION_WA5PEFILEMENU:
  141. {
  142. wa2.triggerPEFileMenu(p1, p2, width, height);
  143. break;
  144. }
  145. case ACTION_WA5PEPLAYLISTMENU:
  146. {
  147. wa2.triggerPEPlaylistMenu(p1, p2, width, height);
  148. break;
  149. }
  150. case ACTION_WA5PESORTMENU:
  151. {
  152. wa2.triggerPESortMenu(p1, p2, width, height);
  153. break;
  154. }
  155. case ACTION_WA5PEHELPMENU:
  156. {
  157. wa2.triggerPEHelpMenu(p1, p2, width, height);
  158. break;
  159. }
  160. case ACTION_WA5MLFILEMENU:
  161. {
  162. wa2.triggerMLFileMenu(p1, p2, width, height);
  163. break;
  164. }
  165. case ACTION_WA5MLVIEWMENU:
  166. {
  167. wa2.triggerMLViewMenu(p1, p2, width, height);
  168. break;
  169. }
  170. case ACTION_WA5MLHELPMENU:
  171. {
  172. wa2.triggerMLHelpMenu(p1, p2, width, height);
  173. break;
  174. }
  175. case ACTION_PEADD:
  176. {
  177. wa2.sendPlCmd(Winamp2FrontEnd::WA2_PLEDITPOPUP_ADD, r.left, r.top, TPM_BOTTOMALIGN | TPM_LEFTALIGN);
  178. break;
  179. }
  180. case ACTION_PEREM:
  181. {
  182. wa2.sendPlCmd(Winamp2FrontEnd::WA2_PLEDITPOPUP_REM, r.left, r.top, TPM_BOTTOMALIGN | TPM_LEFTALIGN);
  183. break;
  184. }
  185. case ACTION_PESEL:
  186. {
  187. wa2.sendPlCmd(Winamp2FrontEnd::WA2_PLEDITPOPUP_SEL, r.left, r.top, TPM_BOTTOMALIGN | TPM_LEFTALIGN);
  188. break;
  189. }
  190. case ACTION_PEMISC:
  191. {
  192. wa2.sendPlCmd(Winamp2FrontEnd::WA2_PLEDITPOPUP_MISC, r.left, r.top, TPM_BOTTOMALIGN | TPM_LEFTALIGN);
  193. break;
  194. }
  195. case ACTION_PELIST:
  196. {
  197. wa2.sendPlCmd(Winamp2FrontEnd::WA2_PLEDITPOPUP_LIST, r.right, r.top, TPM_BOTTOMALIGN | TPM_RIGHTALIGN);
  198. break;
  199. }
  200. case ACTION_PELISTOFLISTS:
  201. {
  202. wa2.triggerPEListOfListsMenu(r.left, r.top);
  203. break;
  204. }
  205. case ACTION_VIDFS:
  206. {
  207. wa2.sendVidCmd(Winamp2FrontEnd::WA2_VIDCMD_FULLSCREEN);
  208. break;
  209. }
  210. case ACTION_VID1X:
  211. {
  212. wa2.sendVidCmd(Winamp2FrontEnd::WA2_VIDCMD_1X);
  213. break;
  214. }
  215. case ACTION_VID2X:
  216. {
  217. wa2.sendVidCmd(Winamp2FrontEnd::WA2_VIDCMD_2X);
  218. break;
  219. }
  220. case ACTION_VIDTV:
  221. {
  222. wa2.sendVidCmd(Winamp2FrontEnd::WA2_VIDCMD_LIB);
  223. break;
  224. }
  225. case ACTION_VIDMISC:
  226. {
  227. wa2.sendVidCmd(Winamp2FrontEnd::WA2_VIDPOPUP_MISC, r.right, r.top, TPM_BOTTOMALIGN | TPM_RIGHTALIGN);
  228. break;
  229. }
  230. case ACTION_VISNEXT:
  231. {
  232. wa2.visNext();
  233. break;
  234. }
  235. case ACTION_VISPREV:
  236. {
  237. wa2.visPrev();
  238. break;
  239. }
  240. case ACTION_VISFS:
  241. {
  242. wa2.visFullscreen();
  243. break;
  244. }
  245. case ACTION_VISCFG:
  246. {
  247. wa2.visConfig();
  248. break;
  249. }
  250. case ACTION_VISMENU:
  251. {
  252. wa2.visMenu();
  253. break;
  254. }
  255. case ACTION_TRACKMENU:
  256. {
  257. extern const wchar_t *GetMenuItemString(HMENU menu, int id, int bypos);
  258. #define WINAMP_TOGGLE_AUTOSCROLL 40189
  259. #define ID_RATING5 40396
  260. #define ID_RATING4 40397
  261. #define ID_RATING3 40398
  262. #define ID_RATING2 40399
  263. #define ID_RATING1 40400
  264. #define ID_RATING0 40401
  265. HMENU top_menu = wa2.getTopMenu();
  266. HMENU contextmenus = GetSubMenu(top_menu, 3);
  267. HMENU songinfomenu = GetSubMenu(contextmenus, 0);
  268. HMENU ratingmenu = GetSubMenu(songinfomenu, 5);
  269. int rating = wa2.getCurTrackRating();
  270. CheckMenuItem(ratingmenu, ID_RATING5, (rating == 5) ? MF_CHECKED : MF_UNCHECKED);
  271. CheckMenuItem(ratingmenu, ID_RATING4, (rating == 4) ? MF_CHECKED : MF_UNCHECKED);
  272. CheckMenuItem(ratingmenu, ID_RATING3, (rating == 3) ? MF_CHECKED : MF_UNCHECKED);
  273. CheckMenuItem(ratingmenu, ID_RATING2, (rating == 2) ? MF_CHECKED : MF_UNCHECKED);
  274. CheckMenuItem(ratingmenu, ID_RATING1, (rating == 1) ? MF_CHECKED : MF_UNCHECKED);
  275. CheckMenuItem(ratingmenu, ID_RATING0, (rating == 0) ? MF_CHECKED : MF_UNCHECKED);
  276. StringW olditemstr = GetMenuItemString(songinfomenu, 3, TRUE);
  277. RemoveMenu(songinfomenu, 3, MF_BYPOSITION);
  278. LRESULT IPC_LIBRARY_SENDTOMENU = SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"LibrarySendToMenu", IPC_REGISTER_WINAMP_IPCMESSAGE);
  279. HMENU menu = 0;
  280. memset(&mainSendTo, 0, sizeof(mainSendTo));
  281. if (IPC_LIBRARY_SENDTOMENU > 65536 && SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)0, IPC_LIBRARY_SENDTOMENU) == 0xffffffff)
  282. {
  283. char stStr[32] = {0};
  284. MENUITEMINFOA mii = {sizeof(mii), MIIM_SUBMENU | MIIM_TYPE, MFT_STRING, };
  285. mii.hSubMenu = menu = CreatePopupMenu();
  286. mii.dwTypeData = WASABI_API_LNGSTRING_BUF(IDS_SEND_TO,stStr,32);
  287. mii.cch = strlen((char*)mii.dwTypeData);
  288. InsertMenuItemA(songinfomenu, 3, TRUE, &mii);
  289. mainSendTo.mode = 1;
  290. mainSendTo.hwnd = plugin.hwndParent; // TODO???
  291. mainSendTo.data_type = ML_TYPE_FILENAMESW;
  292. mainSendTo.build_hMenu = menu;
  293. }
  294. menufucker_t mf = {sizeof(mf),MENU_SONGTICKER,songinfomenu,0x3000,0x4000,0};
  295. pluginMessage message_build = {SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"menufucker_build", IPC_REGISTER_WINAMP_IPCMESSAGE),(intptr_t)&mf,0};
  296. sendMlIpc(ML_IPC_SEND_PLUGIN_MESSAGE,(WPARAM)&message_build);
  297. int ret = DoTrackPopup(songinfomenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON|TPM_RETURNCMD, p1, p2, wa2.getMainWindow());
  298. pluginMessage message_result = {SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"menufucker_result", IPC_REGISTER_WINAMP_IPCMESSAGE),(intptr_t)&mf,ret,0};
  299. sendMlIpc(ML_IPC_SEND_PLUGIN_MESSAGE,(WPARAM)&message_result);
  300. if (menu)
  301. {
  302. if (mainSendTo.mode == 2)
  303. {
  304. mainSendTo.menu_id = ret;
  305. if (SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&mainSendTo, IPC_LIBRARY_SENDTOMENU) == 0xffffffff)
  306. {
  307. wchar_t buf[FILENAME_SIZE + 1] = {0};
  308. wchar_t *end=buf;
  309. size_t endSize = 0;
  310. const wchar_t *entry = wa2.getFileW(wa2.getCurPlaylistEntry());
  311. if (entry && *entry)
  312. {
  313. StringCchCopyExW(buf, FILENAME_SIZE, entry, &end, &endSize, 0);
  314. mainSendTo.mode = 3;
  315. mainSendTo.data = buf;
  316. mainSendTo.data_type = ML_TYPE_FILENAMESW;
  317. SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&mainSendTo, IPC_LIBRARY_SENDTOMENU);
  318. }
  319. }
  320. }
  321. // remove sendto
  322. DeleteMenu(songinfomenu, 3, MF_BYPOSITION);
  323. }
  324. if (mainSendTo.mode)
  325. {
  326. mainSendTo.mode = 4;
  327. SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&mainSendTo, IPC_LIBRARY_SENDTOMENU); // cleanup
  328. memset(&mainSendTo, 0, sizeof(mainSendTo));
  329. }
  330. InsertMenuW(songinfomenu, 3, MF_BYPOSITION | MF_STRING, WINAMP_TOGGLE_AUTOSCROLL, olditemstr);
  331. if (ret) SendMessageW(wa2.getMainWindow(), WM_COMMAND, ret, 0); // TODO?
  332. break;
  333. }
  334. case ACTION_SENDTO:
  335. {
  336. LRESULT IPC_LIBRARY_SENDTOMENU = SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"LibrarySendToMenu", IPC_REGISTER_WINAMP_IPCMESSAGE);
  337. HMENU menu = 0;
  338. memset(&mainSendTo, 0, sizeof(mainSendTo));
  339. if (IPC_LIBRARY_SENDTOMENU > 65536 && SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)0, IPC_LIBRARY_SENDTOMENU) == 0xffffffff)
  340. {
  341. menu = CreatePopupMenu();
  342. mainSendTo.mode = 1;
  343. mainSendTo.hwnd = plugin.hwndParent; // TODO???
  344. mainSendTo.data_type = ML_TYPE_FILENAMESW;
  345. mainSendTo.build_hMenu = menu;
  346. }
  347. int ret = DoTrackPopup(menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON|TPM_RETURNCMD, p1, p2, wa2.getMainWindow());
  348. if (menu)
  349. {
  350. if (mainSendTo.mode == 2)
  351. {
  352. mainSendTo.menu_id = ret;
  353. if (SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&mainSendTo, IPC_LIBRARY_SENDTOMENU) == 0xffffffff)
  354. {
  355. wchar_t buf[FILENAME_SIZE + 1] = {0};
  356. wchar_t *end=buf;
  357. size_t endSize = 0;
  358. const wchar_t *entry = wa2.getFileW(wa2.getCurPlaylistEntry());
  359. if (entry && *entry)
  360. {
  361. StringCchCopyExW(buf, FILENAME_SIZE, entry, &end, &endSize, 0);
  362. mainSendTo.mode = 3;
  363. mainSendTo.data = buf;
  364. mainSendTo.data_type = ML_TYPE_FILENAMESW;
  365. SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&mainSendTo, IPC_LIBRARY_SENDTOMENU);
  366. }
  367. }
  368. }
  369. }
  370. if (mainSendTo.mode)
  371. {
  372. mainSendTo.mode = 4;
  373. SendMessageW(plugin.hwndParent, WM_WA_IPC, (WPARAM)&mainSendTo, IPC_LIBRARY_SENDTOMENU); // cleanup
  374. memset(&mainSendTo, 0, sizeof(mainSendTo));
  375. }
  376. }
  377. break;
  378. case ACTION_TRACKINFO:
  379. {
  380. wa2.openTrackInfo();
  381. break;
  382. }
  383. }
  384. in_menu = 0;
  385. return 1;
  386. }
  387. HMENU MenuActions::makeSkinOptionsSubMenu(GUID g, int *cmdoffset)
  388. {
  389. CfgItem *item = WASABI_API_CONFIG->config_getCfgItemByGuid(g);
  390. if (item != NULL)
  391. {
  392. HMENU menu = CreatePopupMenu();
  393. int n = MIN(item->getNumAttributes(), 500);
  394. for (int i = 0;i < n;i++)
  395. {
  396. const wchar_t *attr = item->enumAttribute(i);
  397. if (attr && *attr)
  398. {
  399. HMENU submenu = NULL;
  400. wchar_t txt[256] = {0};
  401. item->getData(attr, txt, 256);
  402. GUID g = nsGUID::fromCharW(txt);
  403. if (g != INVALID_GUID)
  404. { // submenu !
  405. submenu = makeSkinOptionsSubMenu(g, cmdoffset);
  406. }
  407. int v = item->getDataAsInt(attr, 0);
  408. if (WCSCASEEQLSAFE(txt, L"-"))
  409. {
  410. InsertMenu(menu, i, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
  411. }
  412. else
  413. InsertMenuW(menu, i, ((v && !submenu) ? MF_CHECKED : MF_UNCHECKED) | MF_STRING | MF_BYPOSITION | (submenu ? MF_POPUP : 0), submenu ? (UINT_PTR)submenu : 44000 + *cmdoffset, _(attr));
  414. }
  415. (*cmdoffset)++;
  416. }
  417. return menu;
  418. }
  419. return NULL;
  420. }
  421. void MenuActions::installSkinOptions(HMENU menu)
  422. {
  423. optionsmenu_wa = 0;
  424. HMENU omenu = NULL;
  425. if (menu == NULL)
  426. {
  427. optionsmenu_wa = 1;
  428. menu = wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_OPTIONS);
  429. omenu = GetSubMenu(wa2.getPopupMenu(), 11 + wa2.adjustOptionsPopupMenu(0));
  430. }
  431. int pos2 = 12;
  432. int cmdoffset = 0;
  433. int pos = optionsmenu_wa ? wa2.adjustFFOptionsMenu(0) + 6 + NUMSTATICWINDOWS /*+ 1*//* + 9*/ : 0;
  434. lowest_itempos = pos;
  435. int insertedline = 0;
  436. if (menu && optionsmenuitems)
  437. {
  438. int n = MIN(optionsmenuitems->getNumAttributes(), 500);
  439. for (int i = 0;i < n;i++)
  440. {
  441. const wchar_t *attr = optionsmenuitems->enumAttribute(i);
  442. if (attr && *attr)
  443. {
  444. HMENU submenu = NULL;
  445. wchar_t txt[256] = {0};
  446. optionsmenuitems->getData(attr, txt, 256);
  447. GUID g = nsGUID::fromCharW(txt);
  448. if (g != INVALID_GUID)
  449. { // submenu !
  450. submenu = makeSkinOptionsSubMenu(g, &cmdoffset);
  451. if (submenu)
  452. menulist.addItem(submenu);
  453. }
  454. int v = optionsmenuitems->getDataAsInt(attr, 0);
  455. if (optionsmenu_wa && !insertedline)
  456. {
  457. wa2.adjustFFOptionsMenu(1);
  458. insertedline = 1;
  459. InsertMenu(menu, pos++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
  460. if (omenu) InsertMenu(omenu, pos2++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
  461. }
  462. if (optionsmenu_wa) wa2.adjustFFOptionsMenu(1);
  463. if (WCSCASEEQLSAFE(txt, L"-"))
  464. {
  465. InsertMenu(menu, pos++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
  466. if (omenu) InsertMenu(omenu, pos2++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
  467. }
  468. else
  469. InsertMenuW(menu, pos++, (v ? MF_CHECKED : MF_UNCHECKED) | MF_STRING | MF_BYPOSITION | (submenu ? MF_POPUP : 0), submenu ? (UINT_PTR)submenu : 44000 + cmdoffset, _(attr));
  470. if (omenu) InsertMenuW(omenu, pos2++, (v ? MF_CHECKED : MF_UNCHECKED) | MF_STRING | MF_BYPOSITION | (submenu ? MF_POPUP : 0), submenu ? (UINT_PTR)submenu : 44000 + cmdoffset, _(attr));
  471. }
  472. cmdoffset++;
  473. }
  474. ffoptionstop = 44000 + cmdoffset;
  475. }
  476. // insert colorthemes submenu
  477. if (omenu)
  478. {
  479. PtrListQuickSorted<ColorThemeSlot, ColorThemeSlotSort> sortedthemes;
  480. int fn = MIN(WASABI_API_SKIN->colortheme_getNumColorSets(), 500);
  481. for (int t = 0;t < fn;t++)
  482. sortedthemes.addItem(new ColorThemeSlot(WASABI_API_SKIN->colortheme_enumColorSet(t), t));
  483. if (!insertedline)
  484. {
  485. wa2.adjustFFOptionsMenu(1);
  486. InsertMenu(menu, pos++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
  487. if (omenu) InsertMenu(omenu, pos2++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
  488. }
  489. HMENU submenu = CreatePopupMenu();
  490. if (WASABI_API_SKIN->colortheme_getNumColorSets() == 0)
  491. {
  492. InsertMenuW(submenu, 0, MF_GRAYED | MF_STRING | MF_BYPOSITION, 0, WASABI_API_LNGSTRINGW(IDS_NO_THEME_AVAILABLE));
  493. }
  494. else
  495. {
  496. int n = sortedthemes.getNumItems();
  497. for (int i = 0;i < n;i++)
  498. {
  499. const wchar_t *ct = sortedthemes.enumItem(i)->name;
  500. int entry = sortedthemes.enumItem(i)->entry;
  501. int iscurrent = WCSCASEEQLSAFE(ct, WASABI_API_SKIN->colortheme_getColorSet());
  502. InsertMenuW(submenu, i, (iscurrent ? MF_CHECKED : MF_UNCHECKED) | MF_STRING | MF_BYPOSITION, 44500 + entry, ct);
  503. }
  504. }
  505. if (optionsmenu_wa) wa2.adjustFFOptionsMenu(1);
  506. InsertMenuW(menu, pos++, MF_STRING | MF_BYPOSITION | (submenu ? MF_POPUP : 0), submenu ? (UINT_PTR)submenu : 44000 + cmdoffset, WASABI_API_LNGSTRINGW(IDS_COLOR_THEMES));
  507. if (omenu) InsertMenuW(omenu, pos2++, MF_STRING | MF_BYPOSITION | (submenu ? MF_POPUP : 0), submenu ? (UINT_PTR)submenu : 44000 + cmdoffset, WASABI_API_LNGSTRINGW(IDS_COLOR_THEMES));
  508. cmdoffset++;
  509. sortedthemes.deleteAll();
  510. }
  511. highest_itempos = pos;
  512. }
  513. void MenuActions::removeSkinOptions()
  514. {
  515. if (highest_itempos == -1 || !optionsmenu_wa) return ;
  516. for (int j = 0;j < menulist.getNumItems();j++)
  517. DestroyMenu(menulist.enumItem(j));
  518. menulist.removeAll();
  519. HMENU menu = wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_OPTIONS);
  520. HMENU omenu = GetSubMenu(wa2.getPopupMenu(), 11 + wa2.adjustOptionsPopupMenu(0));
  521. if (menu && optionsmenuitems)
  522. {
  523. for (int i = lowest_itempos;i < highest_itempos;i++)
  524. {
  525. RemoveMenu(menu, lowest_itempos, MF_BYPOSITION);
  526. if (omenu) RemoveMenu(omenu, 12, MF_BYPOSITION);
  527. wa2.adjustFFOptionsMenu( -1);
  528. }
  529. }
  530. highest_itempos = -1;
  531. }
  532. int MenuActions::toggleOption(int n, GUID guid, int *cmdoffset)
  533. {
  534. int _cmdoffset = 0;
  535. if (!cmdoffset) cmdoffset = &_cmdoffset;
  536. CfgItem *item = NULL;
  537. if (guid == INVALID_GUID)
  538. item = optionsmenuitems;
  539. else
  540. item = WASABI_API_CONFIG->config_getCfgItemByGuid(guid);
  541. if (!item) // not sure why this happens, but it happened in a crash report so I'm going to check for it.
  542. return 1; // TODO: guru
  543. for (int i = 0; i < item->getNumAttributes();i++)
  544. {
  545. const wchar_t *name = item->enumAttribute(i);
  546. if (name && *name)
  547. {
  548. wchar_t txt[256] = {0};
  549. item->getData(name, txt, 256);
  550. GUID g = nsGUID::fromCharW(txt);
  551. if (g != INVALID_GUID)
  552. { // submenu !
  553. if (toggleOption(n, g, cmdoffset)) return 1;
  554. }
  555. if (*cmdoffset == n)
  556. {
  557. int newv = item->getDataAsInt(name) ? 0 : 1;
  558. item->setDataAsInt(name, newv);
  559. return 1;
  560. }
  561. }
  562. (*cmdoffset)++;
  563. }
  564. return 0;
  565. }
  566. const wchar_t* MenuActions::localizeSkinWindowName(const wchar_t* attr)
  567. {
  568. static wchar_t tweaked_attr[96];
  569. ZERO(tweaked_attr);
  570. // allows us to map some of the common actions to localised versions (primarily with bundled skins)
  571. if(!_wcsicmp(attr,L"Equalizer\tAlt+G"))
  572. {
  573. // if there's a match then we can force things to use the previous menu
  574. // string (fixes localisation inconsistancy without altering the scripts!)
  575. lstrcpynW(tweaked_attr, eqmenustring, 96);
  576. }
  577. else if(!_wcsicmp(attr,L"Skin Settings\tAlt+C"))
  578. {
  579. WASABI_API_LNGSTRINGW_BUF(IDS_SKIN_SETTINGS,tweaked_attr,96);
  580. }
  581. else if(!_wcsicmp(attr,L"Web Browser\tAlt+X"))
  582. {
  583. WASABI_API_LNGSTRINGW_BUF(IDS_WEB_BROWSER,tweaked_attr,96);
  584. }
  585. else if(!_wcsicmp(attr,L"Album Art\tAlt+A"))
  586. {
  587. WASABI_API_LNGSTRINGW_BUF(IDS_ALBUM_ART,tweaked_attr,96);
  588. }
  589. else if(!_wcsicmp(attr,L"Color Editor"))
  590. {
  591. WASABI_API_LNGSTRINGW_BUF(IDS_COLOR_EDITOR,tweaked_attr,96);
  592. }
  593. else
  594. {
  595. return attr;
  596. }
  597. return tweaked_attr;
  598. }
  599. // FIX ME - menu weirdness going on!!
  600. void MenuActions::installSkinWindowOptions()
  601. {
  602. HMENU menu = wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_WINDOWS);
  603. int pos = lowest_witempos = wa2.adjustFFWindowsMenu(0) + NUMSTATICWINDOWS;
  604. HMENU omenu = wa2.getPopupMenu();
  605. int pos2 = lowest_witempos2 = wa2.adjustOptionsPopupMenu(0) + 6 + NUMSTATICWINDOWS + 1;
  606. MENUITEMINFOW mii = {sizeof(mii), };
  607. mii.fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU;
  608. mii.fType = MFT_STRING;
  609. mii.wID = 42000;
  610. mii.dwItemData = 0xD02; // use this as a check so we're only removing the correct items!!
  611. if (menu && windowsmenuitems)
  612. {
  613. int n = MIN(windowsmenuitems->getNumAttributes(), 500);
  614. int cmdoffset = 0;
  615. for (int i = 0;i < n;i++)
  616. {
  617. const wchar_t *attr = windowsmenuitems->enumAttribute(i);
  618. if (attr && *attr)
  619. {
  620. HMENU submenu = NULL;
  621. wchar_t txt[256] = {0};
  622. windowsmenuitems->getData(attr, txt, 256);
  623. GUID g = nsGUID::fromCharW(txt);
  624. if (g != INVALID_GUID)
  625. { // submenu !
  626. submenu = makeSkinOptionsSubMenu(g, &cmdoffset);
  627. if (submenu)
  628. wmenulist.addItem(submenu);
  629. }
  630. int v = windowsmenuitems->getDataAsInt(attr, 0);
  631. wa2.adjustFFWindowsMenu(1);
  632. wa2.adjustOptionsPopupMenu(1);
  633. attr = localizeSkinWindowName(attr);
  634. const wchar_t* t = _(attr);
  635. mii.dwTypeData = const_cast<wchar_t *>(t);
  636. if (WCSCASEEQLSAFE(txt, L"-"))
  637. {
  638. InsertMenu(menu, pos++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
  639. InsertMenu(omenu, pos2++, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
  640. }
  641. else{
  642. mii.cch = wcslen(mii.dwTypeData);
  643. mii.fState = (v ? MFS_CHECKED : 0);
  644. mii.wID = 42000 + cmdoffset;
  645. mii.hSubMenu = submenu;
  646. InsertMenuItemW(menu, pos++, TRUE, &mii);
  647. }
  648. InsertMenuItemW(omenu, pos2++, TRUE, &mii);
  649. }
  650. cmdoffset++;
  651. }
  652. ffwoptionstop = 42000 + cmdoffset;
  653. }
  654. highest_witempos = pos;
  655. highest_witempos2 = pos2;
  656. }
  657. void MenuActions::removeSkinWindowOptions()
  658. {
  659. if (highest_witempos == -1) return ;
  660. for (int j = 0;j < wmenulist.getNumItems();j++)
  661. DestroyMenu(wmenulist.enumItem(j));
  662. wmenulist.removeAll();
  663. HMENU menu = wa2.getMenuBarMenu(Winamp2FrontEnd::WA2_MAINMENUBAR_WINDOWS);
  664. HMENU omenu = wa2.getPopupMenu();
  665. if (menu && windowsmenuitems)
  666. {
  667. for(int i = GetMenuItemCount(menu)-1; i != 0; i--)
  668. {
  669. MENUITEMINFOW info = {sizeof(info), MIIM_DATA, 0, };
  670. if(GetMenuItemInfoW(menu,i,TRUE,&info))
  671. {
  672. if(info.dwItemData == 0xD02){
  673. RemoveMenu(menu,i,MF_BYPOSITION);
  674. wa2.adjustFFWindowsMenu(-1);
  675. }
  676. }
  677. }
  678. for(int i = GetMenuItemCount(omenu)-1; i != 0; i--)
  679. {
  680. MENUITEMINFOW info = {sizeof(info), MIIM_DATA, 0, };
  681. if(GetMenuItemInfoW(omenu,i,TRUE,&info))
  682. {
  683. if(info.dwItemData == 0xD02){
  684. RemoveMenu(omenu,i,MF_BYPOSITION);
  685. wa2.adjustOptionsPopupMenu(-1);
  686. }
  687. }
  688. }
  689. /*for (int i = highest_witempos;i >= lowest_witempos;i--)
  690. {
  691. RemoveMenu(menu, i, MF_BYPOSITION);
  692. wa2.adjustFFWindowsMenu(-1);
  693. }
  694. for (int i = highest_witempos2;i >= lowest_witempos2;i--)
  695. {
  696. RemoveMenu(menu, i, MF_BYPOSITION);
  697. wa2.adjustOptionsPopupMenu(-1);
  698. }
  699. /*/
  700. /*for (int i = lowest_witempos;i < highest_witempos;i++)
  701. {
  702. RemoveMenu(menu, lowest_witempos, MF_BYPOSITION);
  703. wa2.adjustFFWindowsMenu(-1);
  704. }
  705. for (int i = lowest_witempos2;i < highest_witempos2;i++)
  706. {
  707. RemoveMenu(omenu, lowest_witempos2, MF_BYPOSITION);
  708. wa2.adjustOptionsPopupMenu(-1);
  709. }/**/
  710. }
  711. highest_witempos = -1;
  712. highest_witempos2 = -1;
  713. }
  714. int MenuActions::toggleWindowOption(int n, GUID guid, int *cmdoffset)
  715. {
  716. int _cmdoffset = 0;
  717. if (!cmdoffset) cmdoffset = &_cmdoffset;
  718. CfgItem *item = NULL;
  719. if (guid == INVALID_GUID)
  720. item = windowsmenuitems;
  721. else
  722. item = WASABI_API_CONFIG->config_getCfgItemByGuid(guid);
  723. for (int i = 0; i < item->getNumAttributes();i++)
  724. {
  725. const wchar_t *name = item->enumAttribute(i);
  726. if (name && *name)
  727. {
  728. wchar_t txt[256] = {0};
  729. item->getData(name, txt, 256);
  730. GUID g = nsGUID::fromCharW(txt);
  731. if (g != INVALID_GUID)
  732. { // submenu !
  733. if (toggleWindowOption(n, g, cmdoffset)) return 1;
  734. }
  735. if (*cmdoffset == n)
  736. {
  737. int newv = item->getDataAsInt(name) ? 0 : 1;
  738. item->setDataAsInt(name, newv);
  739. return 1;
  740. }
  741. }
  742. (*cmdoffset)++;
  743. }
  744. return 0;
  745. }