1
0

queries.cpp 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639
  1. #include "main.h"
  2. #include "ml_local.h"
  3. #include "resource.h"
  4. #include "..\..\General\gen_ml/gaystring.h"
  5. #include "..\..\General\gen_ml/config.h"
  6. #include "..\..\General\gen_ml/ml_ipc.h"
  7. #include "../nde/nde.h"
  8. #include "editquery.h"
  9. #include "../nu/ComboBox.h"
  10. #include "../replicant/nu/AutoWide.h"
  11. #include "../replicant/nu/AutoChar.h"
  12. #include "../replicant/nu/ns_wc.h"
  13. #include "..\..\General\gen_ml/ml_ipc_0313.h"
  14. const wchar_t *getFilterName(unsigned int filterId, wchar_t *buffer, size_t bufferSize);
  15. static int m_edit_item;
  16. void queryStrEscape(const wchar_t *p, GayStringW &str)
  17. {
  18. if (!p || !*p) return;
  19. size_t l = wcslen(p);
  20. wchar_t *escaped = (wchar_t *)calloc((l*3+1), sizeof(wchar_t));
  21. wchar_t *d = escaped;
  22. while (p && *p) {
  23. if (*p == L'%') { *d++ = L'%'; *d++ = L'%'; }
  24. else if (*p == L'\"') { *d++ = L'%'; *d++ = L'2'; *d++ = L'2'; }
  25. else if (*p == L'\'') { *d++ = L'%'; *d++ = L'2'; *d++ = L'7'; }
  26. else if (*p == L'[') { *d++ = L'%'; *d++ = L'5'; *d++ = L'B'; }
  27. else if (*p == L']') { *d++ = L'%'; *d++ = L'5'; *d++ = L'D'; }
  28. else if (*p == L'(') { *d++ = L'%'; *d++ = L'2'; *d++ = L'8'; }
  29. else if (*p == L')') { *d++ = L'%'; *d++ = L'2'; *d++ = L'9'; }
  30. else if (*p == L'#') { *d++ = L'%'; *d++ = L'2'; *d++ = L'3'; }
  31. else *d++ = *p;
  32. p++;
  33. }
  34. *d = 0;
  35. str.Set(escaped);
  36. free(escaped);
  37. }
  38. static INT_PTR CALLBACK scrollChildHostProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  39. static INT_PTR CALLBACK childAdvanced(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  40. int m_item_mode=0,main_oninitdialog;
  41. int m_item_image = MLTREEIMAGE_DEFAULT;
  42. wchar_t m_item_name[256]=L"";
  43. wchar_t m_item_query[1024]=L"";
  44. typedef struct {
  45. int title;
  46. wchar_t *query;
  47. char sort_by;
  48. char sort_dir;
  49. char *columns; //xff terminated list :). NULL means default columns
  50. int imageIndex;
  51. int mode;
  52. } smartViewPreset;
  53. #define ARTIST 0x01
  54. #define ALBUMARTIST 0x02
  55. #define GENRE 0x03
  56. #define PUBLISHER 0x04
  57. #define COMPOSER 0x05
  58. #define ALBUM 0x06
  59. #define YEAR 0x07
  60. #define ARTISTINDEX 0x08
  61. #define ALBUMARTISTINDEX 0x09
  62. #define PODCASTCHANNEL 0x0A
  63. #define ALBUMART 0x0B
  64. #define MAKEVIEW_3FILTER(a, b, c) (a | (b << 8) | (c << 16))
  65. #define MAKEVIEW_2FILTER(a, b) (a | (b << 8))
  66. static smartViewPreset presets[] = {
  67. {IDS_AUDIO, L"type = 0", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, 1},
  68. {IDS_VIDEO, L"type = 1", 10, 0, "\x7\1\5\x1E\6\3\x20\x8\x9\xA\xff", TREE_IMAGE_LOCAL_VIDEO,MAKEVIEW_2FILTER(GENRE,YEAR)},
  69. {IDS_MOST_PLAYED, L"playcount > 0", 9, 0, "\x9\0\1\2\3\xA\xff", TREE_IMAGE_LOCAL_MOSTPLAYED,0},
  70. {IDS_RECENTLY_ADDED, L"dateadded > [3 days ago]", 33, 0, "\x21\0\1\2\3\xff", TREE_IMAGE_LOCAL_RECENTLYADDED,0},
  71. {IDS_RECENTLY_MODIFIED, L"lastupd > [3 days ago]", 11, 0, "\xB\0\1\2\3\xff", TREE_IMAGE_LOCAL_RECENTLYMODIFIED,0},
  72. {IDS_RECENTLY_PLAYED, L"lastplay > [2 weeks ago]", 10, 0, "\xA\x9\0\1\2\3\xff", TREE_IMAGE_LOCAL_RECENTLYPLAYED,0},
  73. {IDS_NEVER_PLAYED, L"playcount = 0 | playcount isempty", 0, 0, "\0\1\2\3\xff", TREE_IMAGE_LOCAL_NEVERPLAYED,0},
  74. {IDS_TOP_RATED, L"rating >= 3", 8, 0, "\x8\x9\0\1\2\3\xff", TREE_IMAGE_LOCAL_TOPRATED,0},
  75. {IDS_PODCASTS,L"ispodcast = 1", 0, 0, 0, TREE_IMAGE_LOCAL_PODCASTS, MAKEVIEW_3FILTER(GENRE,PODCASTCHANNEL,YEAR)},
  76. {IDS_AUDIO_BY_GENRE, L"type = 0", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, MAKEVIEW_3FILTER(GENRE,ARTIST,ALBUM)},
  77. {IDS_AUDIO_BY_INDEX, L"type = 0", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, MAKEVIEW_3FILTER(ARTISTINDEX,ARTIST,ALBUM)},
  78. {IDS_SIMPLE_ALBUM, L"type = 0", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, 0x0100000B},
  79. {IDS_60s_MUSIC, L"type = 0 and year >= 1960 and year < 1970", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, 1},
  80. {IDS_70s_MUSIC, L"type = 0 and year >= 1970 and year < 1980", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, 1},
  81. {IDS_80s_MUSIC, L"type = 0 and year >= 1980 and year < 1990", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, 1},
  82. {IDS_90s_MUSIC, L"type = 0 and year >= 1990 and year < 2000", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, 1},
  83. {IDS_00s_MUSIC, L"type = 0 and year >= 2000 and year < 2010", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, 1},
  84. {IDS_ROCK_MUSIC, L"type = 0 and genre has \"Rock\"", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, 1},
  85. {IDS_CLASSICAL_MUSIC, L"type = 0 and genre has \"Classical\"", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, MAKEVIEW_2FILTER(COMPOSER,ALBUM)},
  86. {IDS_RECORD_LABELS, L"type = 0", 0, 0, NULL, TREE_IMAGE_LOCAL_AUDIO, MAKEVIEW_3FILTER(PUBLISHER,ALBUMARTIST,ALBUM)},
  87. {IDS_CUSTOM, L"", 0, 0, NULL, MLTREEIMAGE_DEFAULT, 0},
  88. };
  89. #define NUM_PRESETS (sizeof(presets) / sizeof(smartViewPreset))
  90. void showdlgelements(HWND hwndDlg, int nCmdShow) {
  91. const int dlgelems[] = {
  92. IDC_STATIC_FILTER,
  93. IDC_RADIO_SIMPLE,
  94. IDC_IMAGE_SIMPLE,
  95. IDC_STATIC_SIMPLE,
  96. IDC_RADIO_SIMPLEALBUM,
  97. IDC_IMAGE_SIMPLEALBUM,
  98. IDC_STATIC_SIMPLEALBUM,
  99. IDC_RADIO_TWOFILTERS,
  100. IDC_IMAGE_TWOFILTERS,
  101. IDC_STATIC_TWOFILTERS,
  102. IDC_RADIO_THREEFILTERS,
  103. IDC_IMAGE_THREEFILTERS,
  104. IDC_STATIC_THREEFILTERS,
  105. IDC_COMBO_FILTER1,
  106. IDC_COMBO_FILTER2,
  107. IDC_COMBO_FILTER3,
  108. IDC_STATIC_FILTER2,
  109. IDC_STATIC_FILTER3,
  110. };
  111. for(int i=0; i < (sizeof(dlgelems)/sizeof(int)); i++)
  112. ShowWindow(GetDlgItem(hwndDlg,dlgelems[i]),nCmdShow);
  113. }
  114. #define SPL_RemoveAll(hwnd) SendMessage(hwnd,WM_USER+41,0,0)
  115. #define SPL_GetQueryString(hwnd) SendMessage(hwnd,WM_USER+40, 0 ,0)
  116. #define SPL_AddFilter(hwnd, filter) (HWND)scrollChildHostProc(hwnd,WM_USER+32, (WPARAM)filter, (LPARAM)1)
  117. #define SPL_AddBlankFilter(hwnd) (HWND)scrollChildHostProc(hwnd,WM_USER+32, 0, (LPARAM)2)
  118. #define SPL_RemoveFilter(hwnd, filterhwnd) SendMessage(hwnd,WM_USER+34,(WPARAM)filterhwnd,(LPARAM)-1)
  119. #define SPL_UpdateScroll(hwnd) SendMessage(hwnd,WM_USER+33,0,0)
  120. static int m_simple_dirty;
  121. void SetStaticItemImage(HWND hwndDlg, UINT ctrl_id, UINT ctrl_img)
  122. {
  123. SendDlgItemMessage(hwndDlg,ctrl_id,STM_SETIMAGE,IMAGE_BITMAP,
  124. (LPARAM)LoadImage(WASABI_API_ORIG_HINST,MAKEINTRESOURCE(ctrl_img),IMAGE_BITMAP,0,0,LR_SHARED));
  125. }
  126. int ResizeComboBoxDropDownW(HWND hwndDlg, UINT id, const wchar_t *str, int width){
  127. SIZE size = {0};
  128. HWND control = GetDlgItem(hwndDlg, id);
  129. HDC hdc = GetDC(control);
  130. // get and select parent dialog's font so that it'll calculate things correctly
  131. HFONT font = (HFONT)SendMessage(hwndDlg,WM_GETFONT,0,0), oldfont = (HFONT)SelectObject(hdc,font);
  132. GetTextExtentPoint32W(hdc, str, wcslen(str)+1, &size);
  133. int ret = width;
  134. if(size.cx > width)
  135. {
  136. SendDlgItemMessage(hwndDlg, id, CB_SETDROPPEDWIDTH, size.cx, 0);
  137. ret = size.cx;
  138. }
  139. SelectObject(hdc, oldfont);
  140. ReleaseDC(control, hdc);
  141. return ret;
  142. }
  143. struct FiltersContext
  144. {
  145. HWND last1, last2;
  146. int mode;
  147. HWND m_scrollchild;
  148. int *error;
  149. };
  150. static bool EnumFilters(Scanner *scanner, nde_filter_t filter, void *context_in)
  151. {
  152. FiltersContext *context = (FiltersContext *)context_in;
  153. HWND x = SPL_AddFilter(context->m_scrollchild,filter);
  154. if(x) { // we have a filter which talks about a field
  155. context->last2=context->last1;
  156. context->last1=x;
  157. context->mode++;
  158. if(context->mode > 2)
  159. context->error[0]=1; // not in our strict form
  160. } else { // we have an AND, OR or a NOT
  161. int f=NDE_Filter_GetOp(filter);
  162. if(f == FILTER_OR) CheckDlgButton(context->last2,IDC_OR,TRUE);
  163. else if(f == FILTER_AND) CheckDlgButton(context->last2,IDC_AND,TRUE);
  164. else context->error[0]=1; // we can't do FILTER_NOT
  165. context->mode--;
  166. if(context->mode != 1) context->error[0]=1; // not in our strict form
  167. }
  168. return !context->error[0];
  169. }
  170. static INT_PTR CALLBACK addQueryFrameDialogProc2(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  171. static HWND m_scrollchild;
  172. static int m_editting=0;
  173. static C_Config *conf=0;
  174. static wchar_t * m_item_meta;
  175. static int mode;
  176. switch(uMsg)
  177. {
  178. case WM_INITDIALOG:
  179. {
  180. const int filters[] = {IDC_COMBO_FILTER1, IDC_COMBO_FILTER2,IDC_COMBO_FILTER3};
  181. HWND controlWindow;
  182. int iItem;
  183. wchar_t buffer[512] = {0};
  184. mode=0;
  185. m_item_meta=0;
  186. conf=0;
  187. m_simple_dirty=0;
  188. openDb();
  189. CheckDlgButton(hwndDlg,IDC_RADIO_SIMPLE,TRUE);
  190. SetDlgItemTextW(hwndDlg,IDC_STATIC_INFO, WASABI_API_LNGSTRINGW(IDS_WILLS_UBER_STRING));
  191. EnableWindow(GetDlgItem(hwndDlg,IDC_HIDE_EXTINFO), g_config->ReadInt(L"useminiinfo2", 0));
  192. // set up presets combo box
  193. {
  194. controlWindow = GetDlgItem(hwndDlg, IDC_COMBO_PRESETS);
  195. if (NULL != controlWindow)
  196. {
  197. int width = 0;
  198. for(size_t i=0; i < NUM_PRESETS; i++)
  199. {
  200. if (NULL != WASABI_API_LNGSTRINGW_BUF(presets[i].title, buffer, ARRAYSIZE(buffer)))
  201. {
  202. iItem = SendMessageW(controlWindow, CB_ADDSTRING, 0, (LPARAM)buffer);
  203. if (CB_ERR != iItem)
  204. {
  205. width = ResizeComboBoxDropDownW(hwndDlg, IDC_COMBO_PRESETS, buffer, width);
  206. SendMessageW(controlWindow, CB_SETITEMDATA,(WPARAM)iItem, (LPARAM)(i + 1));
  207. }
  208. }
  209. }
  210. }
  211. }
  212. for(size_t i=0; i < ARRAYSIZE(filters); i++)
  213. {
  214. controlWindow = GetDlgItem(hwndDlg, filters[i]);
  215. if (NULL != controlWindow)
  216. {
  217. int width = 0;
  218. for(unsigned int filterId = 0;; filterId++)
  219. {
  220. if (NULL == getFilterName(filterId, buffer, ARRAYSIZE(buffer)))
  221. break;
  222. iItem = SendMessageW(controlWindow, CB_ADDSTRING, 0, (LPARAM)buffer);
  223. if (CB_ERR != iItem)
  224. {
  225. width = ResizeComboBoxDropDownW(hwndDlg, filters[i], buffer, width);
  226. SendMessageW(controlWindow, CB_SETITEMDATA,(WPARAM)iItem, (LPARAM)filterId);
  227. }
  228. }
  229. }
  230. }
  231. if (lParam == 1)
  232. {
  233. if (m_edit_item == -1)
  234. {
  235. // nothing to do, m_item_name, m_item_query & m_item_mode have been set already
  236. }
  237. else
  238. {
  239. lstrcpynW(m_item_name,m_query_list[m_edit_item]->name,sizeof(m_item_name)/sizeof(wchar_t));
  240. lstrcpynW(m_item_query,m_query_list[m_edit_item]->query,sizeof(m_item_query)/sizeof(wchar_t));
  241. m_item_mode = m_query_list[m_edit_item]->mode;
  242. m_item_image = m_query_list[m_edit_item]->imgIndex;
  243. // re-select the preset name if we can get a match to a known preset (looks nicer and all that)
  244. controlWindow = GetDlgItem(hwndDlg, IDC_COMBO_PRESETS);
  245. if (NULL != controlWindow)
  246. {
  247. for(size_t i=0; i < NUM_PRESETS; i++)
  248. {
  249. if(m_item_query[0] && !_wcsicmp(presets[i].query, m_item_query)
  250. && presets[i].mode == m_item_mode)
  251. {
  252. SendMessageW(controlWindow, CB_SETCURSEL, i, 0);
  253. SendMessage(hwndDlg,WM_COMMAND,(WPARAM)MAKEWPARAM(IDC_COMBO_PRESETS,CBN_SELCHANGE),(LPARAM)GetDlgItem(hwndDlg,IDC_COMBO_PRESETS));
  254. break;
  255. }
  256. }
  257. }
  258. // config
  259. wchar_t configDir[MAX_PATH] = {0};
  260. PathCombineW(configDir, g_viewsDir, m_query_list[m_edit_item]->metafn);
  261. conf = new C_Config(configDir);
  262. CheckDlgButton(hwndDlg, IDC_HIDE_EXTINFO, conf->ReadInt(L"midivvis", 1) ? 0 : 1);
  263. }
  264. SetWindowTextW(hwndDlg,WASABI_API_LNGSTRINGW(IDS_EDIT_SMART_VIEW));
  265. m_editting=1;
  266. }
  267. else
  268. {
  269. m_editting=0;
  270. if (m_item_mode != -1) m_item_mode=0;
  271. m_item_name[0]=0;
  272. m_item_query[0]=0;
  273. m_item_image = MLTREEIMAGE_DEFAULT;
  274. wchar_t filename[1024 + 256] = {0};
  275. extern void makemetafn(wchar_t *filename, wchar_t **out);
  276. makemetafn(filename, &m_item_meta);
  277. conf = new C_Config(filename);
  278. }
  279. if(!mode) m_scrollchild=WASABI_API_CREATEDIALOGW(IDD_SCROLLCHILDHOST,hwndDlg,scrollChildHostProc);
  280. else m_scrollchild=WASABI_API_CREATEDIALOGW(IDD_ADD_VIEW_CHILD_ADVANCED,hwndDlg,childAdvanced);
  281. // this will make sure that we've got the little images shown in all languages (done for 5.51+)
  282. SetStaticItemImage(hwndDlg,IDC_IMAGE_SIMPLE,IDB_NEWFILTER_SIMPLE);
  283. SetStaticItemImage(hwndDlg,IDC_IMAGE_SIMPLEALBUM,IDB_NEWFILTER_SIMPLEALBUM);
  284. SetStaticItemImage(hwndDlg,IDC_IMAGE_TWOFILTERS,IDB_NEWFILTER_TWOFILTERS);
  285. SetStaticItemImage(hwndDlg,IDC_IMAGE_THREEFILTERS,IDB_NEWFILTER_THREEFILTERS);
  286. if(m_editting==0 && g_config->ReadInt(L"newfilter_showhelp",1))
  287. {
  288. showdlgelements(hwndDlg,SW_HIDE);
  289. ShowWindow(hwndDlg,SW_SHOWNA);
  290. EnableWindow(GetParent(hwndDlg),0);
  291. break; // don't run through
  292. }
  293. else
  294. {
  295. ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC_INFO),SW_HIDE);
  296. ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK_SHOWINFO),SW_HIDE);
  297. // run through
  298. }
  299. }
  300. case WM_USER+9:
  301. { // do stuff when we're shown or preset is changed
  302. showdlgelements(hwndDlg,SW_SHOWNA);
  303. ShowWindow(m_scrollchild,SW_SHOWNA);
  304. // set up filter radio buttons and combo boxes
  305. extern int GetFilter(int mode, int n);
  306. extern int GetNumFilters(int mode);
  307. int numFilters=GetNumFilters(m_item_mode);
  308. int f[3] = {0};
  309. f[0] = GetFilter(m_item_mode,0);
  310. f[1] = GetFilter(m_item_mode,1);
  311. f[2] = GetFilter(m_item_mode,2);
  312. if(numFilters==0) CheckRadioButton(hwndDlg,IDC_RADIO_TWOFILTERS,IDC_RADIO_SIMPLEALBUM,IDC_RADIO_SIMPLE);
  313. else if(numFilters==1) CheckRadioButton(hwndDlg,IDC_RADIO_TWOFILTERS,IDC_RADIO_SIMPLEALBUM,IDC_RADIO_SIMPLEALBUM);
  314. else if(numFilters==2) CheckRadioButton(hwndDlg,IDC_RADIO_TWOFILTERS,IDC_RADIO_SIMPLEALBUM,IDC_RADIO_TWOFILTERS);
  315. else if(numFilters==3) CheckRadioButton(hwndDlg,IDC_RADIO_TWOFILTERS,IDC_RADIO_SIMPLEALBUM,IDC_RADIO_THREEFILTERS);
  316. for(int i=0; i<3; i++) {
  317. ComboBox comboBox(hwndDlg, (i==0)?IDC_COMBO_FILTER1:((i==1)?IDC_COMBO_FILTER2:IDC_COMBO_FILTER3));
  318. if(f[i]==0) comboBox.SelectItem(i==0?0:5);
  319. else comboBox.SelectItem(f[i]-1);
  320. }
  321. // set up "name" edit control
  322. SetDlgItemTextW(hwndDlg,IDC_NAME,m_item_name);
  323. // do the query editor thing...
  324. SendMessage(hwndDlg,WM_USER+11,0,0);
  325. }
  326. // run through
  327. case WM_USER+10:
  328. { // enable filter combo boxes based on radio buttons
  329. int numFilters=0;
  330. if(IsDlgButtonChecked(hwndDlg,IDC_RADIO_SIMPLEALBUM)) numFilters=1;
  331. if(IsDlgButtonChecked(hwndDlg,IDC_RADIO_TWOFILTERS)) numFilters=2;
  332. else if(IsDlgButtonChecked(hwndDlg,IDC_RADIO_THREEFILTERS)) numFilters=3;
  333. EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_FILTER3),numFilters>2);
  334. EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_FILTER2),numFilters>1);
  335. EnableWindow(GetDlgItem(hwndDlg,IDC_COMBO_FILTER3),numFilters>2);
  336. EnableWindow(GetDlgItem(hwndDlg,IDC_COMBO_FILTER2),numFilters>1);
  337. EnableWindow(GetDlgItem(hwndDlg,IDC_COMBO_FILTER1),numFilters>1);
  338. if (WM_INITDIALOG == uMsg)
  339. {
  340. // show edit info window and restore last position as applicable
  341. POINT pt = {g_config->ReadInt(L"smart_x", -1), g_config->ReadInt(L"smart_y", -1)};
  342. if (!windowOffScreen(hwndDlg, pt))
  343. SetWindowPos(hwndDlg, HWND_TOP, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOSENDCHANGING);
  344. else
  345. ShowWindow(hwndDlg, SW_SHOWNA);
  346. HWND parentWindow = GetParent(hwndDlg);
  347. if (NULL != parentWindow)
  348. EnableWindow(parentWindow, 0);
  349. }
  350. /*else
  351. ShowWindow(hwndDlg, SW_SHOW);*/
  352. }
  353. break;
  354. case WM_USER+11:
  355. if(!mode) {
  356. SPL_RemoveAll(m_scrollchild);
  357. EnterCriticalSection(&g_db_cs);
  358. nde_scanner_t p=NDE_Table_CreateScanner(g_table);
  359. ((Scanner *)p)->disable_date_resolution=1; // TODO: don't use C++ NDE api
  360. int error=0; // not really an error, just we can't express it properly
  361. if (m_item_query[0] && !NDE_Scanner_Query(p, m_item_query))
  362. error=1; // ok, actually an error.
  363. if (m_item_query[0] && !error)
  364. {
  365. FiltersContext context;
  366. context.error = &error;
  367. context.last1 = 0;
  368. context.last2 = 0;
  369. context.m_scrollchild = m_scrollchild;
  370. context.mode = 0;
  371. ((Scanner *)p)->WalkFilters((Scanner::FilterWalker)EnumFilters, &context); // TODO: don't use C++ NDE api
  372. }
  373. NDE_Table_DestroyScanner(g_table, p);
  374. LeaveCriticalSection(&g_db_cs);
  375. if(error) {
  376. SPL_RemoveAll(m_scrollchild);
  377. HWND x = SPL_AddBlankFilter(m_scrollchild);
  378. ComboBox c(x,IDC_COMBO1);
  379. int n = c.GetCount();
  380. for(int i=0; i<n; i++) if(c.GetItemData(i) == 0x1ea7c0de) c.SelectItem(i);
  381. SetDlgItemTextW(x,IDC_EDIT1,m_item_query);
  382. SendMessage(x,WM_COMMAND,(WPARAM)MAKEWPARAM(IDC_COMBO1,CBN_SELCHANGE),(LPARAM)GetDlgItem(x,IDC_COMBO1));
  383. }
  384. m_simple_dirty=0;
  385. SPL_UpdateScroll(m_scrollchild);
  386. }
  387. break;
  388. case WM_DESTROY:
  389. if(conf) delete conf; conf=0;
  390. if(m_item_meta) free(m_item_meta); m_item_meta=0;
  391. break;
  392. case WM_COMMAND:
  393. switch(LOWORD(wParam)) {
  394. case IDC_BUTTON_MODE:
  395. if(m_simple_dirty)
  396. SPL_GetQueryString(m_scrollchild);
  397. DestroyWindow(m_scrollchild);
  398. mode = !mode;
  399. if(!mode) m_scrollchild=WASABI_API_CREATEDIALOGW(IDD_SCROLLCHILDHOST,hwndDlg,scrollChildHostProc);
  400. else m_scrollchild=WASABI_API_CREATEDIALOGW(IDD_ADD_VIEW_CHILD_ADVANCED,hwndDlg,childAdvanced);
  401. SendMessage(hwndDlg,WM_USER+11,0,0);
  402. SendMessage(hwndDlg,WM_USER+10,0,0);
  403. ShowWindow(m_scrollchild,SW_SHOWNA);
  404. ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC_INFO),SW_HIDE);
  405. ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK_SHOWINFO),SW_HIDE);
  406. SetDlgItemTextW(hwndDlg,IDC_BUTTON_MODE,WASABI_API_LNGSTRINGW( !mode ? IDS_ADVANCED_MODE : IDS_SIMPLE_MODE));
  407. showdlgelements(hwndDlg,SW_SHOWNA);
  408. break;
  409. case IDC_COMBO_PRESETS:
  410. switch(HIWORD(wParam)) {
  411. case CBN_SELCHANGE:
  412. {
  413. ComboBox combo(hwndDlg,IDC_COMBO_PRESETS);
  414. int n = combo.GetItemData(combo.GetSelection());
  415. if(n>0 && n<=NUM_PRESETS) {
  416. wchar_t cusStr[16] = {0};
  417. n--;
  418. // populate with a preset
  419. m_item_mode = presets[n].mode;
  420. m_item_image = presets[n].imageIndex;
  421. if(!_wcsicmp(WASABI_API_LNGSTRINGW_BUF(IDS_CUSTOM,cusStr,16),
  422. WASABI_API_LNGSTRINGW(presets[n].title))) m_item_name[0]=0;
  423. else WASABI_API_LNGSTRINGW_BUF(presets[n].title,m_item_name,256);
  424. lstrcpynW(m_item_query,presets[n].query,sizeof(m_item_query)/sizeof(wchar_t));
  425. showdlgelements(hwndDlg,SW_SHOWNA);
  426. ShowWindow(m_scrollchild,SW_SHOWNA);
  427. ShowWindow(GetDlgItem(hwndDlg,IDC_STATIC_INFO),SW_HIDE);
  428. ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK_SHOWINFO),SW_HIDE);
  429. SendMessage(hwndDlg,WM_USER+9,0,0);
  430. }
  431. }
  432. break;
  433. }
  434. break;
  435. // filter type radio buttons (simulate clicks on the radio button when the image or static text gets clicked)
  436. case IDC_CHECK_SHOWINFO:
  437. g_config->WriteInt(L"newfilter_showhelp",0);
  438. break;
  439. case IDC_STATIC_SIMPLE:
  440. case IDC_IMAGE_SIMPLE:
  441. SendMessage(GetDlgItem(hwndDlg,IDC_RADIO_SIMPLE),BM_CLICK,0,0);
  442. break;
  443. case IDC_STATIC_SIMPLEALBUM:
  444. case IDC_IMAGE_SIMPLEALBUM:
  445. SendMessage(GetDlgItem(hwndDlg,IDC_RADIO_SIMPLEALBUM),BM_CLICK,0,0);
  446. break;
  447. case IDC_STATIC_TWOFILTERS:
  448. case IDC_IMAGE_TWOFILTERS:
  449. SendMessage(GetDlgItem(hwndDlg,IDC_RADIO_TWOFILTERS),BM_CLICK,0,0);
  450. break;
  451. case IDC_STATIC_THREEFILTERS:
  452. case IDC_IMAGE_THREEFILTERS:
  453. SendMessage(GetDlgItem(hwndDlg,IDC_RADIO_THREEFILTERS),BM_CLICK,0,0);
  454. break;
  455. // enable filter combo boxes based on radio buttons
  456. case IDC_RADIO_SIMPLE:
  457. case IDC_RADIO_SIMPLEALBUM:
  458. case IDC_RADIO_TWOFILTERS:
  459. case IDC_RADIO_THREEFILTERS:
  460. CheckDlgButton(hwndDlg,IDC_RADIO_SIMPLE,0);
  461. CheckDlgButton(hwndDlg,IDC_RADIO_SIMPLEALBUM,0);
  462. CheckDlgButton(hwndDlg,IDC_RADIO_TWOFILTERS,0);
  463. CheckDlgButton(hwndDlg,IDC_RADIO_THREEFILTERS,0);
  464. CheckDlgButton(hwndDlg,LOWORD(wParam),1);
  465. SendMessage(hwndDlg,WM_USER+10,0,0);
  466. break;
  467. // OK and Cancel buttons
  468. case IDOK:
  469. {
  470. //name
  471. GetDlgItemTextW(hwndDlg,IDC_NAME,m_item_name,255);
  472. m_item_name[255]=0;
  473. if(!m_item_name[0]) {
  474. wchar_t title[64] = {0};
  475. MessageBoxW(hwndDlg,WASABI_API_LNGSTRINGW(IDS_MUST_ENTER_A_NAME),
  476. WASABI_API_LNGSTRINGW_BUF(IDS_ERROR,title,64),MB_OK);
  477. return 0;
  478. }
  479. //query
  480. if (m_simple_dirty)
  481. SPL_GetQueryString(m_scrollchild);
  482. if(IsDlgButtonChecked(hwndDlg,IDC_RADIO_SIMPLEALBUM))
  483. {
  484. if(conf)
  485. {
  486. conf->WriteInt(L"adiv2pos",100000);
  487. conf->WriteInt(L"albumartviewmode",2);
  488. }
  489. m_item_mode = 0x0100000B;
  490. }
  491. else
  492. { // mode
  493. int numFilters=3;
  494. if(IsDlgButtonChecked(hwndDlg,IDC_RADIO_SIMPLE)) numFilters=0;
  495. else if(IsDlgButtonChecked(hwndDlg,IDC_RADIO_TWOFILTERS)) numFilters=2;
  496. int f[3] = {0};
  497. for(int i=0; i<3; i++) {
  498. ComboBox comboBox(hwndDlg, (i==0)?IDC_COMBO_FILTER1:((i==1)?IDC_COMBO_FILTER2:IDC_COMBO_FILTER3));
  499. f[i] = (comboBox.GetItemData(comboBox.GetSelection()) + 1) & 0xff;
  500. }
  501. if(f[1] == 6) f[1]=0;
  502. if(numFilters == 2) f[2]=0;
  503. if(numFilters == 0) f[0]=f[1]=f[2]=0;
  504. m_item_mode = f[0] | (f[1] << 8) | (f[2] << 16);
  505. }
  506. if(conf) {
  507. int v = IsDlgButtonChecked(hwndDlg,IDC_HIDE_EXTINFO)?0:1;
  508. conf->WriteInt(L"midivvis",v);
  509. ComboBox combo(hwndDlg,IDC_COMBO_PRESETS);
  510. int n = combo.GetItemData(combo.GetSelection());
  511. if(n>0 && n<=NUM_PRESETS) {
  512. n--;
  513. conf->WriteInt(L"mv_sort_by", presets[n].sort_by);
  514. conf->WriteInt(L"mv_sort_dir", presets[n].sort_dir);
  515. if(presets[n].columns) {
  516. int cnt = 0;
  517. while ((unsigned char)presets[n].columns[cnt] != 0xff)
  518. {
  519. wchar_t buf[32] = {0};
  520. StringCchPrintfW(buf, ARRAYSIZE(buf), L"column%d", cnt);
  521. conf->WriteInt(buf, (unsigned char)presets[n].columns[cnt]);
  522. cnt++;
  523. }
  524. conf->WriteInt(L"nbcolumns", cnt);
  525. }
  526. }
  527. }
  528. if (m_edit_item == -1) {
  529. // nothing to do, return values are m_item_name, m_item_query and m_item_mode
  530. } else {
  531. if(!m_editting) addQueryItem(m_item_name,m_item_query,m_item_mode,1,m_item_meta, m_item_image);
  532. else replaceQueryItem(m_edit_item,m_item_name,m_item_query,m_item_mode, m_item_image);
  533. saveQueryTree();
  534. }
  535. if(m_editting) PostMessage(plugin.hwndLibraryParent, WM_USER + 30, 0, 0);
  536. }
  537. case IDCANCEL:
  538. {
  539. RECT smart_rect = {0};
  540. GetWindowRect(hwndDlg, &smart_rect);
  541. g_config->WriteInt(L"smart_x", smart_rect.left);
  542. g_config->WriteInt(L"smart_y", smart_rect.top);
  543. EndDialog(hwndDlg,(LOWORD(wParam) == IDOK));
  544. EnableWindow(GetParent(hwndDlg),1);
  545. break;
  546. }
  547. }
  548. break;
  549. }
  550. return 0;
  551. }
  552. static INT_PTR CALLBACK childAdvanced(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) {
  553. switch (uMsg)
  554. {
  555. case WM_INITDIALOG:
  556. {
  557. RECT r;
  558. HWND parentWindow, controlWindow;
  559. parentWindow = GetAncestor(hwndDlg, GA_PARENT);
  560. if (NULL != parentWindow &&
  561. FALSE != GetWindowRect(GetDlgItem(parentWindow,IDC_CHILDFRAME),&r))
  562. {
  563. MapWindowPoints(HWND_DESKTOP, parentWindow, (POINT*)&r, 2);
  564. SetWindowPos(hwndDlg,NULL,r.left,r.top,r.right-r.left,r.bottom-r.top,SWP_NOZORDER|SWP_NOACTIVATE);
  565. }
  566. SetDlgItemTextW(hwndDlg,IDC_QUERY,m_item_query);
  567. controlWindow = GetDlgItem(hwndDlg, IDC_EDIT1);
  568. if (NULL != controlWindow)
  569. {
  570. SetWindowTextA(controlWindow, (char*)WASABI_API_LOADRESFROMFILEW(L"TEXT", MAKEINTRESOURCEW(IDR_QUERIES_TEXT), 0));
  571. }
  572. }
  573. return 1;
  574. case WM_USER+40: // get query str
  575. GetDlgItemTextW(hwndDlg,IDC_QUERY,m_item_query,1024);
  576. break;
  577. case WM_COMMAND:
  578. switch(LOWORD(wParam)) {
  579. case IDC_EDIT:
  580. {
  581. wchar_t query[1024] = {0};
  582. GetDlgItemTextW(hwndDlg,IDC_QUERY,query, 1024);
  583. wchar_t querybuf[4096] = {0};
  584. const wchar_t *newquery = editQuery(hwndDlg, query, querybuf, 4096);
  585. if (newquery != NULL) {
  586. SetDlgItemTextW(hwndDlg, IDC_QUERY, newquery);
  587. m_simple_dirty=1;
  588. }
  589. }
  590. break;
  591. case IDC_QUERY:
  592. m_simple_dirty=1;
  593. break;
  594. }
  595. break;
  596. }
  597. const int controls[] =
  598. {
  599. IDC_EDIT1,
  600. };
  601. if (FALSE != WASABI_API_APP->DirectMouseWheel_ProcessDialogMessage(hwndDlg, uMsg, wParam, lParam, controls, ARRAYSIZE(controls)))
  602. return TRUE;
  603. return 0;
  604. }
  605. BOOL IsDirectMouseWheelMessage(const UINT uMsg)
  606. {
  607. static UINT WINAMP_WM_DIRECT_MOUSE_WHEEL = WM_NULL;
  608. if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL)
  609. {
  610. WINAMP_WM_DIRECT_MOUSE_WHEEL = RegisterWindowMessageW(L"WINAMP_WM_DIRECT_MOUSE_WHEEL");
  611. if (WM_NULL == WINAMP_WM_DIRECT_MOUSE_WHEEL)
  612. return FALSE;
  613. }
  614. return (WINAMP_WM_DIRECT_MOUSE_WHEEL == uMsg);
  615. }
  616. static INT_PTR CALLBACK filterProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  617. {
  618. switch (uMsg)
  619. {
  620. case WM_INITDIALOG:
  621. // populate comboboxes
  622. {
  623. HWND hwndCB=GetDlgItem(hwndDlg,IDC_COMBO1);
  624. int strs[]=
  625. {
  626. IDS_FILENAME,
  627. IDS_TITLE,
  628. IDS_ARTIST,
  629. IDS_ALBUM,
  630. IDS_YEAR,
  631. IDS_GENRE,
  632. IDS_COMMENT,
  633. IDS_TRACK_NUMBER,
  634. IDS_LENGTH,
  635. IDS_IS_VIDEO,
  636. IDS_LAST_UPDATED,
  637. IDS_PLAYED_LAST,
  638. IDS_RATING,
  639. NULL, // fear the 13
  640. NULL, // gracenote
  641. IDS_PLAY_COUNT,
  642. IDS_FILE_TIME,
  643. IDS_FILE_SIZE_KB,
  644. IDS_BITRATE_KBPS,
  645. IDS_DISC_NUMBER,
  646. IDS_ALBUM_ARTIST,
  647. IDS_ALBUM_GAIN,
  648. IDS_TRACK_GAIN,
  649. IDS_PUBLISHER,
  650. IDS_COMPOSER,
  651. IDS_BPM, // no bpm
  652. IDS_DISCS,
  653. IDS_TRACKS,
  654. IDS_IS_PODCAST,
  655. IDS_PODCAST_CHANNEL,
  656. IDS_PODCAST_PUBLISH_DATE,
  657. NULL,
  658. NULL,
  659. IDS_LOSSLESS,
  660. IDS_CATEGORY,
  661. IDS_CODEC,
  662. IDS_DIRECTOR,
  663. IDS_PRODUCER,
  664. IDS_WIDTH,
  665. IDS_HEIGHT,
  666. NULL,
  667. IDS_DATE_ADDED,
  668. };
  669. int x;
  670. int cnt = 0, width = 0;
  671. wchar_t * str;
  672. for (x = 0; x < sizeof(strs)/sizeof(strs[0]); x ++)
  673. {
  674. if (strs[x])
  675. {
  676. int a=SendMessageW(hwndCB, CB_ADDSTRING,0,(LPARAM)(str = WASABI_API_LNGSTRINGW(strs[x])));
  677. width = ResizeComboBoxDropDownW(hwndDlg, IDC_COMBO1, str, width);
  678. SendMessage(hwndCB,CB_SETITEMDATA,(WPARAM)a,(LPARAM)x);
  679. cnt++;
  680. }
  681. }
  682. int a=SendMessageW(hwndCB, CB_ADDSTRING,0,(LPARAM)(str = WASABI_API_LNGSTRINGW(IDS_CUSTOM)));
  683. ResizeComboBoxDropDownW(hwndDlg, IDC_COMBO1, str, width);
  684. SendMessage(hwndCB,CB_SETITEMDATA,(WPARAM)a,(LPARAM)0x1ea7c0de);
  685. cnt++;
  686. if (lParam)
  687. {
  688. nde_filter_t filter=(nde_filter_t)lParam;
  689. int a=NDE_Filter_GetID(filter);
  690. if (a != -1)
  691. {
  692. for (x = 0; x < cnt; x ++)
  693. {
  694. int d = SendMessage(hwndCB,CB_GETITEMDATA,(WPARAM)x,0);
  695. if (d == a)
  696. break;
  697. }
  698. if (x < cnt)
  699. {
  700. SendMessage(hwndCB,CB_SETCURSEL,x,0);
  701. SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_COMBO1,CBN_SELCHANGE),(LPARAM)hwndCB);
  702. int filtop=NDE_Filter_GetOp(filter);
  703. HWND hwndCB2=GetDlgItem(hwndDlg,IDC_COMBO2);
  704. cnt=SendMessage(hwndCB2,CB_GETCOUNT,0,0);
  705. for (x = 0; x < cnt; x ++)
  706. {
  707. if (SendMessage(hwndCB2,CB_GETITEMDATA,(WPARAM)x,0) == filtop)
  708. break;
  709. }
  710. if (x < cnt)
  711. {
  712. SendMessage(hwndCB2,CB_SETCURSEL,x,0);
  713. SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_COMBO2,CBN_SELCHANGE),(LPARAM)hwndCB2);
  714. }
  715. }
  716. }
  717. nde_field_t f=NDE_Filter_GetData(filter);
  718. if (f)
  719. {
  720. int ft=NDE_Field_GetType(f);
  721. //hack cause we never actualy get FIELD_LENGTH here.
  722. if (ft==FIELD_INTEGER && a==MAINTABLE_ID_LENGTH) ft=FIELD_LENGTH;
  723. switch (ft)
  724. {
  725. case FIELD_FILENAME:
  726. case FIELD_STRING:
  727. SetDlgItemTextW(hwndDlg,IDC_EDIT1,NDE_StringField_GetString(f));
  728. break;
  729. case FIELD_LENGTH:
  730. {
  731. int v=NDE_IntegerField_GetValue(f);
  732. wchar_t buf[128] = {0};
  733. if (v < 60)
  734. wsprintf(buf,L"%d",v);
  735. else if (v < 60*60)
  736. wsprintf(buf,L"%d:%02d",v/60,v%60);
  737. else
  738. wsprintf(buf,L"%d:%02d:%02d",v/60/60,(v/60)%60,v%60);
  739. SetDlgItemText(hwndDlg,IDC_EDIT1,buf);
  740. }
  741. break;
  742. case FIELD_INTEGER:
  743. SetDlgItemInt(hwndDlg,IDC_EDIT1,NDE_IntegerField_GetValue(f),TRUE);
  744. break;
  745. }
  746. }
  747. }
  748. }
  749. return 1;
  750. case WM_USER+29:
  751. if(IsDlgButtonChecked(hwndDlg,IDC_AND)) return 1;
  752. if(IsDlgButtonChecked(hwndDlg,IDC_OR)) return 0;
  753. CheckDlgButton(hwndDlg,wParam?IDC_AND:IDC_OR,TRUE);
  754. return wParam;
  755. case WM_USER+40:
  756. if (wParam && lParam>0)
  757. {
  758. wchar_t *buf=(wchar_t *)wParam;
  759. size_t buf_len=(size_t)lParam;
  760. // produce expression here
  761. HWND hwndCB=GetDlgItem(hwndDlg,IDC_COMBO1);
  762. HWND hwndCB2=GetDlgItem(hwndDlg,IDC_COMBO2);
  763. int x=SendMessage(hwndCB,CB_GETCURSEL,0,0);
  764. if (x != CB_ERR)
  765. {
  766. int Id=SendMessage(hwndCB,CB_GETITEMDATA,x,0);
  767. if(Id == 0x1ea7c0de) { // custom!
  768. GetDlgItemTextW(hwndDlg,IDC_EDIT1,buf,buf_len);
  769. return 0;
  770. }
  771. x = SendMessage(hwndCB2,CB_GETCURSEL,0,0);
  772. if (x != CB_ERR)
  773. {
  774. int Op=SendMessage(hwndCB2,CB_GETITEMDATA,x,0);
  775. if (Id != -1 && Op != -1)
  776. {
  777. wchar_t res[256] = {0};
  778. GetDlgItemTextW(hwndDlg,IDC_EDIT1,res,255);
  779. res[255]=0;
  780. nde_field_t p = NDE_Table_GetColumnByID(g_table, (unsigned char)Id);
  781. if (p)
  782. {
  783. const wchar_t *fn=NDE_ColumnField_GetFieldName(p);
  784. wchar_t *opstr=NULL;
  785. switch (Op)
  786. {
  787. case FILTER_EQUALS: opstr=L"="; break;
  788. case FILTER_NOTEQUALS: opstr=L"!="; break;
  789. case FILTER_CONTAINS: opstr=L"HAS"; break;
  790. case FILTER_NOTCONTAINS: opstr=L"NOTHAS"; break;
  791. case FILTER_ABOVE: opstr=L">"; break;
  792. case FILTER_BELOW: opstr=L"<"; break;
  793. case FILTER_ABOVEOREQUAL: opstr=L">="; break;
  794. case FILTER_BELOWOREQUAL: opstr=L"<="; break;
  795. case FILTER_BEGINS: opstr=L"BEGINS"; break;
  796. case FILTER_ENDS: opstr=L"ENDS"; break;
  797. case FILTER_LIKE: opstr=L"LIKE"; break;
  798. case FILTER_ISEMPTY: opstr=L"ISEMPTY"; break;
  799. case FILTER_ISNOTEMPTY: opstr=L"ISNOTEMPTY"; break;
  800. }
  801. if (fn && fn[0] && opstr && opstr[0])
  802. {
  803. if (Op == FILTER_ISEMPTY || Op == FILTER_ISNOTEMPTY)
  804. wsprintfW(buf, L"%s %s",fn,opstr);
  805. else if (NDE_ColumnField_GetDataType(p) == FIELD_DATETIME)
  806. wsprintfW(buf, L"%s %s [%s]",fn,opstr,res);
  807. else
  808. {
  809. GayStringW escaped;
  810. queryStrEscape(res, escaped);
  811. wsprintfW(buf, L"%s %s \"%s\"",fn,opstr,escaped.Get());
  812. }
  813. }
  814. }
  815. }
  816. }
  817. }
  818. }
  819. return 0;
  820. case WM_COMMAND:
  821. switch (LOWORD(wParam))
  822. {
  823. case IDC_BUTTON1:
  824. SendMessage(GetParent(hwndDlg),WM_USER+34,(WPARAM)hwndDlg,-1);
  825. m_simple_dirty=1;
  826. return 0;
  827. case IDC_OR:
  828. case IDC_AND:
  829. m_simple_dirty=1;
  830. break;
  831. case IDC_BUTTON_QUERYBUILD:
  832. {
  833. wchar_t query[1024] = {0};
  834. GetDlgItemTextW(hwndDlg,IDC_EDIT,query, 1024);
  835. wchar_t querybuf[4096] = {0};
  836. const wchar_t *newquery = editQuery(hwndDlg, query, querybuf, 4096);
  837. if (newquery != NULL) {
  838. SetDlgItemTextW(hwndDlg, IDC_EDIT, newquery);
  839. m_simple_dirty=1;
  840. }
  841. }
  842. break;
  843. case IDC_BUTTON2:
  844. {
  845. wchar_t query[1024] = {0};
  846. GetDlgItemTextW(hwndDlg,IDC_EDIT1,query,1024);
  847. const wchar_t *newquery = editTime(hwndDlg, query);
  848. if (newquery != NULL) SetDlgItemTextW(hwndDlg, IDC_EDIT1, newquery);
  849. }
  850. // todo: date picker
  851. return 0;
  852. case IDC_EDIT1:
  853. if (HIWORD(wParam) == EN_CHANGE)
  854. {
  855. m_simple_dirty=1;
  856. }
  857. return 0;
  858. case IDC_COMBO2:
  859. if (HIWORD(wParam) == CBN_SELCHANGE)
  860. {
  861. m_simple_dirty=1;
  862. HWND hwndCB2=(HWND)lParam;
  863. int x=SendMessage(hwndCB2,CB_GETCURSEL,0,0);
  864. if (x != CB_ERR)
  865. {
  866. int a=SendMessage(hwndCB2,CB_GETITEMDATA,(WPARAM)x,0);
  867. if (a == FILTER_ISEMPTY || a == FILTER_ISNOTEMPTY)
  868. {
  869. EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),0);
  870. }
  871. else
  872. {
  873. EnableWindow(GetDlgItem(hwndDlg,IDC_EDIT1),1);
  874. }
  875. }
  876. }
  877. return 0;
  878. case IDC_COMBO1:
  879. if (HIWORD(wParam) == CBN_SELCHANGE)
  880. {
  881. m_simple_dirty=1;
  882. HWND hwndCB=(HWND)lParam;
  883. HWND hwndCB2=GetDlgItem(hwndDlg,IDC_COMBO2);
  884. int x=SendMessage(hwndCB,CB_GETCURSEL,0,0);
  885. #define GAP 2
  886. if (x != CB_ERR)
  887. {
  888. int lastsel=SendMessage(hwndCB2,CB_GETCURSEL,0,0);
  889. SendMessage(hwndCB2,CB_RESETCONTENT,0,0);
  890. // populate with proper comparisons for type. give a default, too
  891. int myId = SendMessage(hwndCB,CB_GETITEMDATA,(WPARAM)x,0);
  892. if(myId == 0x1ea7c0de) { // custom!
  893. ShowWindow(GetDlgItem(hwndDlg,IDC_BUTTON_QUERYBUILD),SW_SHOWNA);
  894. ShowWindow(GetDlgItem(hwndDlg,IDC_COMBO2),SW_HIDE);
  895. RECT r;
  896. GetWindowRect(GetDlgItem(hwndDlg,IDC_BUTTON2),&r);
  897. ScreenToClient(hwndDlg,((LPPOINT)&r));
  898. RECT r1;
  899. GetWindowRect(GetDlgItem(hwndDlg,IDC_COMBO1),&r1);
  900. ScreenToClient(hwndDlg,((LPPOINT)&r1));
  901. ScreenToClient(hwndDlg,((LPPOINT)&r1)+1);
  902. RECT r2;
  903. GetWindowRect(GetDlgItem(hwndDlg,IDC_EDIT1),&r2);
  904. ScreenToClient(hwndDlg,((LPPOINT)&r2));
  905. ScreenToClient(hwndDlg,((LPPOINT)&r2)+1);
  906. SetWindowPos(GetDlgItem(hwndDlg,IDC_EDIT1),0,r1.right+GAP,r1.top,r.left-r1.right-GAP-GAP,r2.bottom-r2.top,/*SWP_NOMOVE|*/SWP_NOACTIVATE|SWP_NOZORDER);
  907. return 0;
  908. }
  909. ShowWindow(GetDlgItem(hwndDlg,IDC_BUTTON_QUERYBUILD),SW_HIDE);
  910. ShowWindow(GetDlgItem(hwndDlg,IDC_COMBO2),SW_SHOWNA);
  911. nde_field_t p = (-1 != myId) ? NDE_Table_GetColumnByID(g_table, (unsigned char)myId) : NULL;
  912. if (p)
  913. {
  914. if (NDE_ColumnField_GetDataType(p)==FIELD_DATETIME)
  915. {
  916. //if (!IsWindowVisible(GetDlgItem(hwndDlg,IDC_BUTTON2)))
  917. {
  918. RECT r;
  919. GetWindowRect(GetDlgItem(hwndDlg,IDC_BUTTON2),&r);
  920. ScreenToClient(hwndDlg,((LPPOINT)&r));
  921. ShowWindow(GetDlgItem(hwndDlg,IDC_BUTTON2),SW_SHOWNA);
  922. RECT r1;
  923. GetWindowRect(GetDlgItem(hwndDlg,IDC_COMBO2),&r1);
  924. ScreenToClient(hwndDlg,((LPPOINT)&r1));
  925. ScreenToClient(hwndDlg,((LPPOINT)&r1)+1);
  926. RECT r2;
  927. GetWindowRect(GetDlgItem(hwndDlg,IDC_EDIT1),&r2);
  928. ScreenToClient(hwndDlg,((LPPOINT)&r2));
  929. ScreenToClient(hwndDlg,((LPPOINT)&r2)+1);
  930. SetWindowPos(GetDlgItem(hwndDlg,IDC_EDIT1),0,r1.right+GAP,r1.top,r.left-r1.right-GAP-GAP,r2.bottom-r2.top,/*SWP_NOMOVE|*/SWP_NOACTIVATE|SWP_NOZORDER);
  931. }
  932. }
  933. else
  934. {
  935. //if (IsWindowVisible(GetDlgItem(hwndDlg,IDC_BUTTON2)))
  936. {
  937. RECT r;
  938. GetWindowRect(GetDlgItem(hwndDlg,IDC_BUTTON2),&r);
  939. ScreenToClient(hwndDlg,((LPPOINT)&r) + 1);
  940. ShowWindow(GetDlgItem(hwndDlg,IDC_BUTTON2),SW_HIDE);
  941. RECT r1;
  942. GetWindowRect(GetDlgItem(hwndDlg,IDC_COMBO2),&r1);
  943. ScreenToClient(hwndDlg,((LPPOINT)&r1));
  944. ScreenToClient(hwndDlg,((LPPOINT)&r1)+1);
  945. RECT r2;
  946. GetWindowRect(GetDlgItem(hwndDlg,IDC_EDIT1),&r2);
  947. ScreenToClient(hwndDlg,((LPPOINT)&r2));
  948. ScreenToClient(hwndDlg,((LPPOINT)&r2)+1);
  949. SetWindowPos(GetDlgItem(hwndDlg,IDC_EDIT1),0,r1.right+GAP,r1.top,r.right-r1.right-GAP,r2.bottom-r2.top,/*SWP_NOMOVE|*/SWP_NOACTIVATE|SWP_NOZORDER);
  950. }
  951. }
  952. #undef GAP
  953. typedef struct
  954. {
  955. int str;
  956. char id;
  957. } fillT;
  958. int myfillt_len=0;
  959. fillT *myfillt=NULL;
  960. static fillT foo1[]=
  961. {
  962. {IDS_EQUALS,FILTER_EQUALS},
  963. {IDS_DOES_NOT_EQUAL,FILTER_NOTEQUALS},
  964. {IDS_CONTAINS,FILTER_CONTAINS},
  965. {IDS_DOES_NOT_CONTAIN,FILTER_NOTCONTAINS},
  966. {IDS_IS_ABOVE,FILTER_ABOVE},
  967. {IDS_IS_BELOW,FILTER_BELOW},
  968. {IDS_EQUALS_OR_IS_ABOVE,FILTER_ABOVEOREQUAL},
  969. {IDS_EQUALS_OR_IS_BELOW,FILTER_BELOWOREQUAL},
  970. {IDS_IS_EMPTY,FILTER_ISEMPTY},
  971. {IDS_IS_NOT_EMPTY,FILTER_ISNOTEMPTY},
  972. {IDS_BEGINS_WITH,FILTER_BEGINS},
  973. {IDS_ENDS_WITH,FILTER_ENDS},
  974. {IDS_IS_SIMILAR_TO,FILTER_LIKE},
  975. };
  976. static fillT foo2[]=
  977. {
  978. {IDS_AT,FILTER_EQUALS},
  979. {IDS_NOT_AT,FILTER_NOTEQUALS},
  980. {IDS_AFTER,FILTER_ABOVE},
  981. {IDS_BEFORE,FILTER_BELOW},
  982. {IDS_SINCE,FILTER_ABOVEOREQUAL},
  983. {IDS_UNTIL,FILTER_BELOWOREQUAL},
  984. {IDS_IS_EMPTY,FILTER_ISEMPTY},
  985. {IDS_IS_NOT_EMPTY,FILTER_ISNOTEMPTY},
  986. };
  987. switch (NDE_ColumnField_GetDataType(p))
  988. {
  989. case FIELD_DATETIME:
  990. {
  991. myfillt_len = sizeof(foo2)/sizeof(foo2[0]);
  992. myfillt=foo2;
  993. }
  994. break;
  995. case FIELD_LENGTH:
  996. case FIELD_INTEGER:
  997. {
  998. myfillt_len = sizeof(foo1)/sizeof(foo1[0]) - 3;
  999. myfillt=foo1;
  1000. }
  1001. break;
  1002. case FIELD_FILENAME:
  1003. case FIELD_STRING:
  1004. {
  1005. myfillt_len = sizeof(foo1)/sizeof(foo1[0]);
  1006. myfillt=foo1;
  1007. }
  1008. break;
  1009. default:
  1010. break;
  1011. }
  1012. if (myfillt)
  1013. {
  1014. wchar_t *str;
  1015. int width = 0;
  1016. while (myfillt_len--)
  1017. {
  1018. int a=SendMessageW(hwndCB2,CB_ADDSTRING,0,(LPARAM)(str = WASABI_API_LNGSTRINGW(myfillt->str)));
  1019. width = ResizeComboBoxDropDownW(hwndDlg, IDC_COMBO2, str, width);
  1020. SendMessage(hwndCB2,CB_SETITEMDATA,a,(LPARAM)myfillt->id);
  1021. myfillt++;
  1022. }
  1023. if (lastsel != CB_ERR)
  1024. SendMessage(hwndCB2,CB_SETCURSEL,lastsel,0);
  1025. }
  1026. }
  1027. }
  1028. }
  1029. return 0;
  1030. }
  1031. return 0;
  1032. }
  1033. if (FALSE != IsDirectMouseWheelMessage(uMsg) ||
  1034. WM_MOUSEWHEEL == uMsg)
  1035. {
  1036. HWND parentWindow;
  1037. parentWindow = GetAncestor(hwndDlg, GA_PARENT);
  1038. if (NULL != parentWindow)
  1039. {
  1040. SendMessageW(parentWindow, WM_MOUSEWHEEL, wParam, lParam);
  1041. SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, (long)TRUE);
  1042. return TRUE;
  1043. }
  1044. }
  1045. return 0;
  1046. }
  1047. static INT_PTR CALLBACK scrollChildProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  1048. {
  1049. static int osize;
  1050. switch (uMsg)
  1051. {
  1052. case WM_INITDIALOG:
  1053. {
  1054. RECT r;
  1055. GetClientRect(hwndDlg,&r);
  1056. osize=r.bottom;
  1057. }
  1058. return 1;
  1059. case WM_COMMAND:
  1060. if (LOWORD(wParam) == IDC_BUTTON1)
  1061. SPL_AddBlankFilter(hwndDlg);
  1062. return 0;
  1063. case WM_USER+40: // get query string
  1064. if (!lParam)
  1065. {
  1066. // now we go through our children, asking each one for a string, and combine them.
  1067. GayStringW str;
  1068. HWND h=GetWindow(hwndDlg,GW_CHILD);
  1069. wchar_t * nextop=NULL;
  1070. while (h)
  1071. {
  1072. if (h != GetDlgItem(hwndDlg,IDC_BUTTON1))
  1073. {
  1074. wchar_t buf[512] = {0};
  1075. buf[0]=0;
  1076. SendMessage(h,WM_USER+40,(WPARAM)buf,(LPARAM)sizeof(buf)/sizeof(*buf));
  1077. if (buf[0])
  1078. {
  1079. if(nextop) str.Append(nextop);
  1080. nextop = IsDlgButtonChecked(h,IDC_AND) ? L" AND " : L" OR ";
  1081. //if (str.Get() && str.Get()[0]) str.Append(isOr ? L" OR " : L" AND ");
  1082. str.Append(buf);
  1083. }
  1084. }
  1085. h=GetWindow(h,GW_HWNDNEXT);
  1086. }
  1087. lstrcpynW(m_item_query,str.Get()?str.Get():L"",sizeof(m_item_query)/sizeof(*m_item_query));
  1088. }
  1089. return 0;
  1090. case WM_USER+41: // remove all
  1091. {
  1092. HWND h=GetWindow(hwndDlg,GW_CHILD);
  1093. std::vector<void*> w;
  1094. while (h) {
  1095. if (h != GetDlgItem(hwndDlg,IDC_BUTTON1))
  1096. w.push_back((void*)h);
  1097. h=GetWindow(h,GW_HWNDNEXT);
  1098. }
  1099. for ( void *l_w : w )
  1100. SendMessage( hwndDlg, WM_USER + 34, (WPARAM)(HWND)l_w, -1 );
  1101. }
  1102. break;
  1103. case WM_USER+34: // remove filter by hwnd
  1104. if (wParam && lParam == -1)
  1105. {
  1106. HWND hwndRemove = (HWND) wParam;
  1107. RECT r;
  1108. GetClientRect(hwndRemove,&r);
  1109. int lh=r.bottom; // height to remove
  1110. GetWindowRect(hwndRemove,&r);
  1111. ScreenToClient(hwndDlg,(LPPOINT)&r);
  1112. int ltop=r.top;
  1113. DestroyWindow(hwndRemove);
  1114. HWND h=GetWindow(hwndDlg,GW_CHILD);
  1115. while (h)
  1116. {
  1117. RECT r;
  1118. GetWindowRect(h,&r);
  1119. ScreenToClient(hwndDlg,(LPPOINT)&r);
  1120. if (r.top > ltop)
  1121. {
  1122. SetWindowPos(h,0,r.left,r.top - lh,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  1123. }
  1124. h=GetWindow(h,GW_HWNDNEXT);
  1125. }
  1126. GetClientRect(hwndDlg,&r);
  1127. r.bottom -= lh;
  1128. SetWindowPos(hwndDlg,0,0,0,r.right,r.bottom,SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
  1129. SendMessage(GetParent(hwndDlg),WM_USER+33,17,0);
  1130. }
  1131. return 0;
  1132. case WM_USER+32: // add filter. lParam is mode. 1 means add by filter, 2 means add blank
  1133. if(lParam == 2) {
  1134. BOOL b=0;
  1135. HWND h=GetWindow(hwndDlg,GW_CHILD);
  1136. while (h) {
  1137. if (h != GetDlgItem(hwndDlg,IDC_BUTTON1))
  1138. b = filterProc(h,WM_USER+29,(WPARAM)b,0);
  1139. h=GetWindow(h,GW_HWNDNEXT);
  1140. }
  1141. }
  1142. if ((lParam == 1 && wParam) || (lParam == 2 && !wParam))
  1143. {
  1144. HWND newChild=0;
  1145. nde_filter_t filter=(nde_filter_t)wParam;
  1146. if (lParam == 2 || (NULL != NDE_Table_GetColumnByID(g_table, NDE_Filter_GetID(filter))))
  1147. {
  1148. newChild=WASABI_API_CREATEDIALOGPARAMW(IDD_SCROLLCHILDFILTER,hwndDlg,filterProc,(LPARAM)filter);
  1149. RECT r,r2;
  1150. GetClientRect(hwndDlg,&r);
  1151. GetClientRect(newChild,&r2);
  1152. SetWindowPos(hwndDlg,0,0,0,r.right,r.bottom + r2.bottom,SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
  1153. SetWindowPos(newChild,0,0,r.bottom - osize,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  1154. HWND h = GetDlgItem(hwndDlg,IDC_BUTTON1);
  1155. GetWindowRect(h,&r);
  1156. ScreenToClient(hwndDlg,(LPPOINT)&r);
  1157. SetWindowPos(h,0,r.left,r.top + r2.bottom,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  1158. ShowWindow(newChild,SW_SHOWNA);
  1159. }
  1160. if (lParam == 2) {
  1161. // update scroll, hugging bottom
  1162. SendMessage(GetParent(hwndDlg),WM_USER+33,16,0);
  1163. }
  1164. return (intptr_t)newChild;
  1165. }
  1166. return 0;
  1167. }
  1168. if (FALSE != IsDirectMouseWheelMessage(uMsg) ||
  1169. WM_MOUSEWHEEL == uMsg)
  1170. {
  1171. HWND parentWindow;
  1172. parentWindow = GetAncestor(hwndDlg, GA_PARENT);
  1173. if (NULL != parentWindow)
  1174. {
  1175. SendMessageW(parentWindow, WM_MOUSEWHEEL, wParam, lParam);
  1176. SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, (long)TRUE);
  1177. return TRUE;
  1178. }
  1179. }
  1180. return 0;
  1181. }
  1182. static INT_PTR CALLBACK scrollChildHostProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  1183. {
  1184. static HWND m_child;
  1185. switch (uMsg)
  1186. {
  1187. case WM_INITDIALOG:
  1188. {
  1189. RECT r;
  1190. GetWindowRect(GetDlgItem(GetParent(hwndDlg),IDC_CHILDFRAME),&r);
  1191. ScreenToClient(GetParent(hwndDlg),(LPPOINT)&r);
  1192. ScreenToClient(GetParent(hwndDlg),((LPPOINT)&r)+1);
  1193. SetWindowPos(hwndDlg,NULL,r.left,r.top,r.right-r.left,r.bottom-r.top,SWP_NOZORDER|SWP_NOACTIVATE);
  1194. }
  1195. m_child=WASABI_API_CREATEDIALOGW(IDD_SCROLLCHILD,hwndDlg,scrollChildProc);
  1196. return 1;
  1197. case WM_USER+33:
  1198. if (m_child)
  1199. {
  1200. RECT r;
  1201. RECT r2;
  1202. GetClientRect(hwndDlg,&r2);
  1203. GetClientRect(m_child,&r);
  1204. if (r2.bottom < r.bottom)
  1205. {
  1206. SCROLLINFO si={sizeof(si),SIF_RANGE|SIF_PAGE|SIF_POS,0,r.bottom,r2.bottom,wParam == 16 ? r.bottom : 0,0};
  1207. if (wParam == 17)
  1208. si.fMask &= ~SIF_POS;
  1209. SetScrollInfo(hwndDlg,SB_VERT,&si,TRUE);
  1210. if (wParam != 17)
  1211. SetWindowPos(m_child,NULL,0,wParam == 16 ? r2.bottom-r.bottom : 0,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  1212. } else {
  1213. //hide the scrollbar
  1214. SetWindowPos(m_child,NULL,0,0,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  1215. ShowScrollBar(hwndDlg,SB_VERT,FALSE);
  1216. }
  1217. ShowWindow(m_child,SW_SHOWNA);
  1218. }
  1219. return 0;
  1220. case WM_USER+32:
  1221. case WM_USER+41:
  1222. case WM_USER+40:
  1223. if (m_child) return scrollChildProc(m_child,uMsg,wParam,lParam);
  1224. return 0;
  1225. case WM_VSCROLL:
  1226. {
  1227. RECT r;
  1228. RECT r2;
  1229. GetClientRect(hwndDlg,&r2);
  1230. GetClientRect(m_child,&r);
  1231. if (r2.bottom < r.bottom)
  1232. {
  1233. int v=0;
  1234. if (LOWORD(wParam) == SB_THUMBPOSITION || LOWORD(wParam) == SB_THUMBTRACK)
  1235. {
  1236. SCROLLINFO si={sizeof(si),SIF_TRACKPOS|SIF_POS};
  1237. GetScrollInfo(hwndDlg,SB_VERT,&si);
  1238. v=si.nTrackPos;
  1239. }
  1240. else if (LOWORD(wParam) == SB_TOP)
  1241. {
  1242. v=0;
  1243. }
  1244. else if (LOWORD(wParam) == SB_BOTTOM)
  1245. {
  1246. v=r.bottom-r2.bottom;
  1247. }
  1248. else if (LOWORD(wParam) == SB_PAGEDOWN || LOWORD(wParam) == SB_LINEDOWN)
  1249. {
  1250. SCROLLINFO si={sizeof(si),SIF_TRACKPOS|SIF_POS};
  1251. GetScrollInfo(hwndDlg,SB_VERT,&si);
  1252. v=si.nPos + r2.bottom;
  1253. if (v > r.bottom-r2.bottom) v=r.bottom-r2.bottom;
  1254. }
  1255. else if (LOWORD(wParam) == SB_PAGEUP || LOWORD(wParam) == SB_LINEUP)
  1256. {
  1257. SCROLLINFO si={sizeof(si),SIF_TRACKPOS|SIF_POS};
  1258. GetScrollInfo(hwndDlg,SB_VERT,&si);
  1259. v=si.nPos - r2.bottom;
  1260. if (v < 0) v=0;
  1261. }
  1262. else return 0;
  1263. SetScrollPos(hwndDlg,SB_VERT,v,!(LOWORD(wParam) == SB_THUMBPOSITION || LOWORD(wParam) == SB_THUMBTRACK));
  1264. SetWindowPos(m_child,NULL,0,0-v,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  1265. }
  1266. else
  1267. {
  1268. SetScrollPos(hwndDlg,SB_VERT,0,!(LOWORD(wParam) == SB_THUMBPOSITION || LOWORD(wParam) == SB_THUMBTRACK));
  1269. SetWindowPos(m_child,NULL,0,0,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  1270. }
  1271. }
  1272. return 0;
  1273. }
  1274. if (FALSE != IsDirectMouseWheelMessage(uMsg) ||
  1275. WM_MOUSEWHEEL == uMsg)
  1276. {
  1277. WORD scrollCommand;
  1278. short delta;
  1279. delta = HIWORD(wParam);
  1280. scrollCommand = (delta > 0) ? SB_LINEUP : SB_LINEDOWN;
  1281. SendMessageW(hwndDlg, WM_VSCROLL, MAKEWPARAM(scrollCommand, 0), 0L);
  1282. }
  1283. return 0;
  1284. }
  1285. void addNewQuery(HWND parent) {
  1286. HWND hwnd = WASABI_API_CREATEDIALOGPARAMW(IDD_ADD_VIEW_2, parent, addQueryFrameDialogProc2, 0);
  1287. SetActiveWindow(hwnd);
  1288. }
  1289. void queryEditItem(int n)
  1290. {
  1291. m_edit_item=n;
  1292. HWND hwnd = WASABI_API_CREATEDIALOGPARAMW(IDD_ADD_VIEW_2, plugin.hwndLibraryParent, addQueryFrameDialogProc2, 1);
  1293. SetActiveWindow(hwnd);
  1294. }
  1295. // returns true if edition was validated, false if cancel was clicked
  1296. // actual return values are in m_item_query, m_item_name and m_item_mode
  1297. int queryEditOther(HWND hwnd, const char *query, const char *viewname, int mode)
  1298. {
  1299. int notnew=1;
  1300. if (query == NULL || !*query) notnew = 0;
  1301. m_edit_item = -1;
  1302. if (notnew)
  1303. {
  1304. MultiByteToWideCharSZ(CP_ACP, 0, viewname, -1, m_item_name, 256);
  1305. MultiByteToWideCharSZ(CP_ACP, 0, query, -1, m_item_query, 1024);
  1306. }
  1307. m_item_mode = mode;
  1308. if(mode == -1)
  1309. return WASABI_API_DIALOGBOXPARAMW(IDD_ADD_VIEW_2_NF, hwnd, addQueryFrameDialogProc2, notnew);
  1310. else
  1311. return WASABI_API_DIALOGBOXPARAMW(IDD_ADD_VIEW_2, hwnd, addQueryFrameDialogProc2, notnew);
  1312. }
  1313. void queryDeleteItem(HWND parent, int n)
  1314. {
  1315. QueryList::iterator iter;
  1316. iter = m_query_list.find(n);
  1317. if (iter == m_query_list.end()) return;
  1318. wchar_t title[64] = {0};
  1319. queryItem *item = iter->second;
  1320. if (MessageBoxW(parent,WASABI_API_LNGSTRINGW(IDS_DELETE_THIS_VIEW),
  1321. WASABI_API_LNGSTRINGW_BUF(IDS_CONFIRMATION,title,64),
  1322. MB_YESNO|MB_ICONQUESTION) == IDYES)
  1323. {
  1324. mediaLibrary.RemoveTreeItem(iter->first);
  1325. m_query_list.erase(iter->first);
  1326. saveQueryTree();
  1327. // we deleted the item from the tree, which apparently is enough to close the current dialog if it was
  1328. // the current dialog. hot.
  1329. for(iter = m_query_list.begin(); iter != m_query_list.end(); iter++)
  1330. if(iter->second && iter->second->index > item->index) iter->second->index--;
  1331. wchar_t configDir[MAX_PATH] = {0};
  1332. PathCombineW(configDir, g_viewsDir, item->metafn);
  1333. DeleteFileW(configDir);
  1334. free(item->metafn);
  1335. free(item->name);
  1336. free(item->query);
  1337. free(item);
  1338. }
  1339. }
  1340. int IPC_LIBRARY_SENDTOMENU;
  1341. static librarySendToMenuStruct s_menu;
  1342. static WNDPROC ml_oldWndProc2;
  1343. static INT_PTR CALLBACK ml_newWndProc2(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1344. {
  1345. switch(uMsg)
  1346. {
  1347. case WM_INITMENUPOPUP:
  1348. if (wParam && (HMENU)wParam == s_menu.build_hMenu && s_menu.mode==1)
  1349. {
  1350. myMenu = TRUE;
  1351. if (SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&s_menu, IPC_LIBRARY_SENDTOMENU)==(LRESULT)-1)
  1352. s_menu.mode=2;
  1353. myMenu = FALSE;
  1354. if(ml_oldWndProc2) SetWindowLongPtrW(hwndDlg,GWLP_WNDPROC,(LONG_PTR)ml_oldWndProc2);
  1355. ml_oldWndProc2 = NULL;
  1356. }
  1357. return 0;
  1358. }
  1359. if (ml_oldWndProc2) return CallWindowProc(ml_oldWndProc2,hwndDlg,uMsg,wParam,lParam);
  1360. return 0;
  1361. }
  1362. HMENU main_sendto_hmenu;
  1363. int main_sendto_mode;
  1364. void view_queryContextMenu(INT_PTR param1, HWND hHost, POINTS pts, int n)
  1365. {
  1366. queryItem *item=m_query_list[n];
  1367. if (item == NULL) return;
  1368. ml_oldWndProc2 = (WNDPROC)SetWindowLongPtrW(hHost, GWLP_WNDPROC, (LONG_PTR)ml_newWndProc2);
  1369. HMENU menu=GetSubMenu(g_context_menus,2);
  1370. main_sendto_hmenu=GetSubMenu(menu,2);
  1371. s_menu.mode = 0;
  1372. s_menu.hwnd = 0;
  1373. s_menu.build_hMenu = 0;
  1374. IPC_LIBRARY_SENDTOMENU = SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&"LibrarySendToMenu", IPC_REGISTER_WINAMP_IPCMESSAGE);
  1375. if (IPC_LIBRARY_SENDTOMENU > 65536 && SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)0, IPC_LIBRARY_SENDTOMENU)==(LRESULT)-1)
  1376. {
  1377. s_menu.mode = 1;
  1378. s_menu.hwnd = hHost;
  1379. s_menu.data_type = ML_TYPE_ITEMRECORDLIST;
  1380. s_menu.ctx[1] = 1;
  1381. s_menu.build_hMenu = main_sendto_hmenu;
  1382. }
  1383. POINT pt;
  1384. POINTSTOPOINT(pt, pts);
  1385. if (-1 == pt.x || -1 == pt.y)
  1386. {
  1387. HNAVITEM hItem = (HNAVITEM)param1;
  1388. NAVITEMGETRECT itemRect;
  1389. itemRect.fItem = FALSE;
  1390. itemRect.hItem = hItem;
  1391. if (MLNavItem_GetRect(plugin.hwndLibraryParent, &itemRect))
  1392. {
  1393. MapWindowPoints(hHost, HWND_DESKTOP, (POINT*)&itemRect.rc, 2);
  1394. pt.x = itemRect.rc.left + 2;
  1395. pt.y = itemRect.rc.top + 2;
  1396. }
  1397. }
  1398. UpdateMenuItems(NULL, menu, IDR_QUERY_ACCELERATORS);
  1399. int r = DoTrackPopup(menu, TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
  1400. pt.x, pt.y, hHost, NULL);
  1401. if(ml_oldWndProc2) SetWindowLongPtrW(hHost,GWLP_WNDPROC,(LONG_PTR)ml_oldWndProc2);
  1402. switch(r)
  1403. {
  1404. case ID_QUERYWND_EDIT:
  1405. queryEditItem(n);
  1406. break;
  1407. case ID_QUERYWND_DELETE:
  1408. queryDeleteItem(hHost,n);
  1409. break;
  1410. case ID_QUERYWND_PLAYQUERY:
  1411. {
  1412. wchar_t configDir[MAX_PATH] = {0};
  1413. PathCombineW(configDir, g_viewsDir, item->metafn);
  1414. C_Config viewconf(configDir);
  1415. main_playQuery(&viewconf,item->query,0);
  1416. }
  1417. break;
  1418. case ID_QUERYWND_ENQUEUEQUERY:
  1419. {
  1420. wchar_t configDir[MAX_PATH] = {0};
  1421. PathCombineW(configDir, g_viewsDir, item->metafn);
  1422. C_Config viewconf(configDir);
  1423. main_playQuery(&viewconf,item->query,1);
  1424. }
  1425. break;
  1426. case ID_QUERYMENU_ADDNEWQUERY:
  1427. addNewQuery(hHost);
  1428. break;
  1429. default:
  1430. if (s_menu.mode == 2)
  1431. {
  1432. s_menu.menu_id = r;
  1433. if (SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&s_menu, IPC_LIBRARY_SENDTOMENU) == (LRESULT)-1)
  1434. {
  1435. // build my data.
  1436. s_menu.mode=3;
  1437. s_menu.data_type = ML_TYPE_ITEMRECORDLISTW;
  1438. wchar_t configDir[MAX_PATH] = {0};
  1439. PathCombineW(configDir, g_viewsDir, item->metafn);
  1440. C_Config viewconf(configDir);
  1441. EnterCriticalSection(&g_db_cs);
  1442. nde_scanner_t s=NDE_Table_CreateScanner(g_table);
  1443. NDE_Scanner_Query(s, item->query);
  1444. itemRecordListW obj={0,};
  1445. saveQueryToListW(&viewconf, s, &obj, 0, 0, (resultsniff_funcW)-1);
  1446. NDE_Table_DestroyScanner(g_table, s);
  1447. LeaveCriticalSection(&g_db_cs);
  1448. s_menu.data = (void*)&obj;
  1449. LRESULT result = SendMessage(plugin.hwndWinampParent, WM_WA_IPC,(WPARAM)&s_menu,IPC_LIBRARY_SENDTOMENU);
  1450. if (result != 1)
  1451. {
  1452. s_menu.mode=3;
  1453. s_menu.data_type = ML_TYPE_ITEMRECORDLIST;
  1454. itemRecordList objA={0,};
  1455. convertRecordList(&objA, &obj);
  1456. s_menu.data = (void*)&objA;
  1457. SendMessage(plugin.hwndWinampParent, WM_WA_IPC,(WPARAM)&s_menu,IPC_LIBRARY_SENDTOMENU);
  1458. freeRecordList(&objA);
  1459. }
  1460. freeRecordList(&obj);
  1461. }
  1462. }
  1463. break;
  1464. }
  1465. if (s_menu.mode)
  1466. {
  1467. s_menu.mode=4;
  1468. SendMessage(plugin.hwndWinampParent, WM_WA_IPC,(WPARAM)&s_menu,IPC_LIBRARY_SENDTOMENU); // cleanup
  1469. }
  1470. main_sendto_hmenu=0;
  1471. EatKeyboard();
  1472. }
  1473. void queriesContextMenu(INT_PTR param1, HWND hHost, POINTS pts) {
  1474. POINT pt;
  1475. POINTSTOPOINT(pt, pts);
  1476. if (-1 == pt.x || -1 == pt.y)
  1477. {
  1478. HNAVITEM hItem = (HNAVITEM)param1;
  1479. NAVITEMGETRECT itemRect;
  1480. itemRect.fItem = FALSE;
  1481. itemRect.hItem = hItem;
  1482. if (MLNavItem_GetRect(plugin.hwndLibraryParent, &itemRect))
  1483. {
  1484. MapWindowPoints(hHost, HWND_DESKTOP, (POINT*)&itemRect.rc, 2);
  1485. pt.x = itemRect.rc.left + 2;
  1486. pt.y = itemRect.rc.top + 2;
  1487. }
  1488. }
  1489. HMENU menu=GetSubMenu(g_context_menus,3);
  1490. int r = DoTrackPopup(menu, TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTBUTTON | TPM_NONOTIFY,
  1491. pt.x, pt.y, hHost, NULL);
  1492. switch(r) {
  1493. case ID_QUERYMENU_ADDNEWQUERY:
  1494. addNewQuery(hHost);
  1495. break;
  1496. case ID_QUERYMENU_PREFERENCES:
  1497. SENDWAIPC(plugin.hwndWinampParent, IPC_OPENPREFSTOPAGE, &preferences);
  1498. break;
  1499. case ID_QUERYMENU_HELP:
  1500. SENDWAIPC(plugin.hwndWinampParent, IPC_OPEN_URL, L"https://help.winamp.com/hc/articles/8105304048660-The-Winamp-Media-Library");
  1501. break;
  1502. }
  1503. EatKeyboard();
  1504. }