AlbumArtRetrieval.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. // disabled 30 May 2012 as per email from Tejas w.r.t. to Rovi deal ending
  2. #if 0
  3. #include "main.h"
  4. #include "../nu/AutoUrl.h"
  5. #include "../nu/AutoWide.h"
  6. #include "../nu/GrowBuf.h"
  7. #include "api.h"
  8. #include "../xml/obj_xml.h"
  9. #include "../xml/ifc_xmlreadercallback.h"
  10. #include "..\Components\wac_network\wac_network_http_receiver_api.h"
  11. #include <api/service/waservicefactory.h>
  12. #include <api/service/svcs/svc_imgload.h>
  13. #include "XMLString.h"
  14. #include <tataki/export.h>
  15. #include <tataki/bitmap/bitmap.h>
  16. #include <tataki/canvas/bltcanvas.h>
  17. #include <strsafe.h>
  18. static INT_PTR CALLBACK artDownloader(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  19. static INT_PTR CALLBACK scrollChildHostProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  20. static INT_PTR CALLBACK scrollChildProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  21. static INT_PTR CALLBACK imageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  22. #define HTTP_BUFFER_SIZE 32768
  23. #define WM_ADDCHILD WM_USER+0
  24. #define WM_SELECTED WM_USER+1
  25. #define WM_UPDATESTATUS WM_USER+2
  26. #define AddImageToList(hChild, param) SendMessageW(hChild,WM_ADDCHILD,0,(LPARAM)param)
  27. #define GetParam(hwndDlg) (ArtParser*)GetWindowLongPtrW(hwndDlg,GWLP_USERDATA)
  28. #define GetParamC(hwndDlg) (ImgDownloader*)GetWindowLongPtrW(hwndDlg,GWLP_USERDATA)
  29. #define UpdateStatus(hwndDlg) PostMessageW(hwndDlg,WM_UPDATESTATUS,0,0)
  30. class ImgDownloader
  31. {
  32. public:
  33. ImgDownloader(const wchar_t *_desc, const char *_url) : done(false), http(0), started(false), error(false), imgbuf(0), imgbufsize(0), imgbufused(0)
  34. {
  35. desc = _wcsdup(_desc);
  36. url = _strdup(_url);
  37. }
  38. ~ImgDownloader()
  39. {
  40. free(desc);
  41. free(url);
  42. free(imgbuf);
  43. waServiceFactory *httpFactory = WASABI_API_SVC->service_getServiceByGuid(httpreceiverGUID);
  44. if(httpFactory && http)
  45. httpFactory->releaseInterface(http);
  46. }
  47. bool run();
  48. wchar_t *desc;
  49. char *url;
  50. bool done, error;
  51. api_httpreceiver *http;
  52. BYTE *imgbuf;
  53. int imgbufsize;
  54. int imgbufused;
  55. private:
  56. bool started;
  57. };
  58. class ArtParser : public ifc_xmlreadercallback
  59. {
  60. public:
  61. ArtParser(artFetchData * data);
  62. ~ArtParser();
  63. wchar_t curAlbumStr[512] = {0};
  64. void ArtParser::StartTag(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
  65. void ArtParser::TextHandler(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *str);
  66. int run();
  67. artFetchData * data;
  68. bool doneXML;
  69. int curImage, numImages, failedImages;
  70. bool error;
  71. HWND hwndDlg;
  72. obj_xml *parser;
  73. waServiceFactory *parserFactory, *httpFactory;
  74. api_httpreceiver *http;
  75. std::vector<ImgDownloader*> imgDownload;
  76. protected:
  77. #define CBCLASS ArtParser
  78. START_DISPATCH_INLINE;
  79. VCB(ONSTARTELEMENT, StartTag);
  80. VCB(ONCHARDATA, TextHandler);
  81. END_DISPATCH;
  82. #undef CBCLASS
  83. };
  84. wchar_t tmp_album[512] = {0}, tmp_artist[512] = {0}, tmp_year[5] = {0};
  85. int RetrieveAlbumArt(artFetchData * data)
  86. {
  87. if(!data || data->size < sizeof(artFetchData))
  88. return 1;
  89. int ret = 1;
  90. Tataki::Init(serviceManager);
  91. {
  92. ArtParser param(data);
  93. if(!param.error)
  94. ret = LPDialogBoxParamW(IDD_ARTDOWNLOADER,data->parent,artDownloader,(LPARAM)&param);
  95. while (ret == 2) // Keep in loop till user aborts custom search
  96. {
  97. // TODO: benski> maybe we should save the old values and restore at the end
  98. data->album = tmp_album;
  99. data->artist = tmp_artist;
  100. data->year = _wtoi(tmp_year);
  101. // Martin> we should also set the other values back to null
  102. // benski> i'm not sure if we want to set these id fields to NULL
  103. // but we'll go with it for now
  104. data->amgAlbumId = NULL;
  105. data->amgArtistId = NULL;
  106. data->gracenoteFileId = NULL;
  107. WASABI_API_MEMMGR->sysFree(data->imgData);
  108. data->imgData = NULL;
  109. data->imgDataLen = NULL;
  110. ArtParser param(data);
  111. ret = LPDialogBoxParamW(IDD_ARTDOWNLOADER,data->parent,artDownloader,(LPARAM)&param);
  112. }
  113. }
  114. Tataki::Quit();
  115. return ret;
  116. }
  117. #define USER_AGENT_SIZE (10 /*User-Agent*/ + 2 /*: */ + 6 /*Winamp*/ + 1 /*/*/ + 1 /*5*/ + 3/*.21*/ + 1 /*Null*/)
  118. static void SetUserAgent(api_httpreceiver *http)
  119. {
  120. char user_agent[USER_AGENT_SIZE] = {0};
  121. StringCchCopyA(user_agent, USER_AGENT_SIZE, "User-Agent: Winamp/"APP_VERSION); // as a nice side effect, this will cut off any extra digits after the first two. e.g. 5.111 becomes 5.11
  122. http->addheader(user_agent);
  123. }
  124. class UrlBuilder : private GrowBuf
  125. {
  126. public:
  127. UrlBuilder(const char * base) : first(1) { set(base); }
  128. ~UrlBuilder(){}
  129. void AddParam(const char * key, const wchar_t * value) { AddParamI(key,(char*)AutoUrl(value)); }
  130. void AddParam(const char * key, int value) { char buf[16]; StringCchPrintfA(buf,16,"%d",value); AddParamI(key,buf); }
  131. void Finish() { GrowBuf::add((void*)"",1); }
  132. const char * Get() { return (const char*)get(); } // don't call this without first calling finish!
  133. private:
  134. void AddParamI(const char * key, const char * value) { if(first){ first=0; add("?");} else add("&"); add(key); add("="); add(value); }
  135. void add(const char * x) { GrowBuf::add((char*)x,strlen(x)); }
  136. void set(const char * x) { GrowBuf::set((char*)x,strlen(x)); }
  137. int first;
  138. };
  139. static wchar_t* format(const wchar_t *in, wchar_t *buf, int len)
  140. {
  141. wchar_t *p = buf;
  142. int inbracket = 0;
  143. while(in && *in)
  144. {
  145. if(p >= buf + len - 1) break;
  146. else if(*in == L'[' || *in == L'(' || *in == L'<') inbracket++;
  147. else if(*in == L']' || *in == L')' || *in == L'>') inbracket--;
  148. else if(!inbracket) *(p++) = *in;
  149. in++;
  150. }
  151. *p=0;
  152. return buf;
  153. }
  154. ArtParser::ArtParser(artFetchData * data) : data(data), error(false), parserFactory(0), parser(0), http(0), httpFactory(0), doneXML(false), curImage(0), numImages(0), failedImages(0)
  155. {
  156. curAlbumStr[0]=0;
  157. parserFactory = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID);
  158. if (parserFactory)
  159. parser = (obj_xml *)parserFactory->getInterface();
  160. if (parser)
  161. {
  162. parser->xmlreader_registerCallback(L"document\fartwork", this);
  163. parser->xmlreader_registerCallback(L"response\fdata\fartwork", this);
  164. parser->xmlreader_open();
  165. }
  166. else
  167. {
  168. error=true;
  169. return;
  170. }
  171. // construct xml url
  172. UrlBuilder url("http://client.winamp.com/metadata/artwork.php");
  173. wchar_t temp[2048] = {0};
  174. if(data->artist && data->artist[0] && _wcsicmp(data->artist, L"Various Artists") && _wcsicmp(data->artist, L"VA") && _wcsicmp(data->artist, L"OST"))
  175. url.AddParam("artist",format(data->artist,temp,2048));
  176. if(data->album && data->album[0])
  177. url.AddParam("album",format(data->album,temp,2048));
  178. if(data->year)
  179. url.AddParam("recorddate",data->year);
  180. if(data->amgAlbumId)
  181. url.AddParam("amgalbumid",data->amgAlbumId);
  182. if(data->amgArtistId)
  183. url.AddParam("amgartistid",data->amgArtistId);
  184. if(data->gracenoteFileId && data->gracenoteFileId[0])
  185. url.AddParam("tagid",data->gracenoteFileId);
  186. url.Finish();
  187. httpFactory = WASABI_API_SVC->service_getServiceByGuid(httpreceiverGUID);
  188. if(httpFactory) http = (api_httpreceiver *)httpFactory->getInterface();
  189. if(http)
  190. {
  191. http->AllowCompression();
  192. http->open(API_DNS_AUTODNS, HTTP_BUFFER_SIZE, config_proxy);
  193. SetUserAgent(http);
  194. http->connect(url.Get());
  195. }
  196. else error = true;
  197. }
  198. ArtParser::~ArtParser()
  199. {
  200. imgDownload.deleteAll();
  201. if(parser)
  202. {
  203. parser->xmlreader_unregisterCallback(this);
  204. parser->xmlreader_close();
  205. if(parserFactory)
  206. parserFactory->releaseInterface(parser);
  207. }
  208. parser = 0;
  209. parserFactory = 0;
  210. if(http && httpFactory)
  211. httpFactory->releaseInterface(http);
  212. http = 0;
  213. httpFactory = 0;
  214. }
  215. void ArtParser::StartTag(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
  216. {
  217. const wchar_t* artist = params->getItemValue(L"amgArtistDispName");
  218. const wchar_t* album = params->getItemValue(L"amgDispName");
  219. const wchar_t* year = params->getItemValue(L"recordDate");
  220. StringCchPrintfW(curAlbumStr,512,L"%s - %s (%s)",artist?artist:L"",album?album:L"",year?year:L"");
  221. }
  222. void ArtParser::TextHandler(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *str)
  223. {
  224. numImages++;
  225. imgDownload.push_back(new ImgDownloader(curAlbumStr,AutoChar(str)));
  226. UpdateStatus(hwndDlg);
  227. }
  228. int ArtParser::run()
  229. {
  230. int ret = http->run();
  231. if (ret == -1) // connection failed
  232. {
  233. error=true;
  234. UpdateStatus(hwndDlg);
  235. return 0;
  236. }
  237. int replycode = http->getreplycode();
  238. switch (replycode)
  239. {
  240. case 0:
  241. case 100:
  242. return 1;
  243. case 200:
  244. {
  245. char downloadedData[HTTP_BUFFER_SIZE] = {0};
  246. int xmlResult = API_XML_SUCCESS;
  247. int downloadSize = http->get_bytes(downloadedData, HTTP_BUFFER_SIZE);
  248. if(downloadSize)
  249. xmlResult = parser->xmlreader_feed((void *)downloadedData, downloadSize);
  250. else if(!downloadSize && ret == 1)
  251. { // we're finished!
  252. xmlResult = parser->xmlreader_feed(0,0);
  253. doneXML=true;
  254. UpdateStatus(hwndDlg);
  255. return 0;
  256. }
  257. break;
  258. }
  259. default:
  260. error=true;
  261. UpdateStatus(hwndDlg);
  262. return 0;
  263. }
  264. return 1;
  265. }
  266. bool ImgDownloader::run()
  267. {
  268. if(!started)
  269. {
  270. started = true;
  271. waServiceFactory *httpFactory = WASABI_API_SVC->service_getServiceByGuid(httpreceiverGUID);
  272. if(httpFactory) http = (api_httpreceiver *)httpFactory->getInterface();
  273. if(http)
  274. {
  275. http->open(API_DNS_AUTODNS, HTTP_BUFFER_SIZE, config_proxy);
  276. SetUserAgent(http);
  277. http->connect(url);
  278. }
  279. imgbuf = (BYTE*)malloc(HTTP_BUFFER_SIZE);
  280. imgbufsize = HTTP_BUFFER_SIZE;
  281. }
  282. if(!http || !imgbuf)
  283. {
  284. error=true;
  285. return 0;
  286. }
  287. int ret = http->run();
  288. if(ret == -1) //error
  289. {
  290. error=true;
  291. return 0;
  292. }
  293. int replycode = http->getreplycode();
  294. switch (replycode)
  295. {
  296. case 0:
  297. case 100:
  298. return 1;
  299. case 200:
  300. {
  301. int downloadSize = http->get_bytes(imgbuf+imgbufused, imgbufsize - imgbufused);
  302. imgbufused += downloadSize;
  303. if(imgbufused + 4096 >= imgbufsize)
  304. {
  305. imgbufsize += HTTP_BUFFER_SIZE;
  306. imgbuf = (BYTE*)realloc(imgbuf,imgbufsize);
  307. }
  308. if(!downloadSize && ret == 1)
  309. done=true;
  310. break;
  311. }
  312. default:
  313. return 0;
  314. }
  315. return 1;
  316. }
  317. static INT_PTR CALLBACK artDownloader(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  318. {
  319. static HWND m_child;
  320. switch(uMsg)
  321. {
  322. case WM_INITDIALOG:
  323. {
  324. m_child = LPCreateDialogW(IDD_ARTDOWNLOADER_SCROLLHOST,hwndDlg,(WNDPROC)scrollChildHostProc);
  325. SetWindowLong(hwndDlg,GWLP_USERDATA,lParam);
  326. ArtParser * parser = (ArtParser *)lParam;
  327. parser->hwndDlg = hwndDlg;
  328. SetTimer(hwndDlg,0,50,NULL);
  329. SetTimer(hwndDlg,1,50,NULL);
  330. UpdateStatus(hwndDlg);
  331. if(parser->data->showCancelAll) ShowWindow(GetDlgItem(hwndDlg,IDC_CANCELALL),SW_SHOWNA);
  332. wchar_t old[100]=L"";
  333. GetWindowTextW(hwndDlg,old,100);
  334. wchar_t buf[256]=L"";
  335. if(parser->data->artist && parser->data->artist[0] && parser->data->album && parser->data->album[0])
  336. StringCchPrintfW(buf,256,L"%s: %s - %s",old,parser->data->artist,parser->data->album);
  337. else if(parser->data->album && parser->data->album[0])
  338. StringCchPrintfW(buf,256,L"%s: %s",old,parser->data->album);
  339. else if(parser->data->artist && parser->data->artist[0])
  340. StringCchPrintfW(buf,256,L"%s: %s",old,parser->data->artist);
  341. if(buf[0])
  342. SetWindowTextW(hwndDlg,buf);
  343. SetWindowTextW(GetDlgItem(hwndDlg,IDC_SEARCHREFINE_ARTIST), parser->data->artist);
  344. SetWindowTextW(GetDlgItem(hwndDlg,IDC_SEARCHREFINE_ALBUM), parser->data->album);
  345. wchar_t yearbuf[5]=L"";
  346. _itow(parser->data->year,yearbuf,10);
  347. SetWindowTextW(GetDlgItem(hwndDlg,IDC_SEARCHREFINE_YEAR), (parser->data->year?yearbuf:L""));
  348. }
  349. break;
  350. case WM_SELECTED:
  351. {
  352. ArtParser * parser = GetParam(hwndDlg);
  353. HWND selchild = (HWND)wParam;
  354. ImgDownloader *d = (ImgDownloader *)lParam;
  355. if(parser && d && d->imgbuf && d->imgbufused)
  356. {
  357. if (!AGAVE_API_AMGSUCKS || AGAVE_API_AMGSUCKS->WriteAlbumArt(d->imgbuf, d->imgbufused, &parser->data->imgData, &parser->data->imgDataLen) != 0)
  358. {
  359. void * img = WASABI_API_MEMMGR->sysMalloc(d->imgbufused);
  360. memcpy(img,d->imgbuf,d->imgbufused);
  361. parser->data->imgData = img;
  362. parser->data->imgDataLen = d->imgbufused;
  363. }
  364. char * dot = strrchr(d->url,'.');
  365. if(dot) lstrcpynW(parser->data->type,AutoWide(dot+1),10);
  366. EndDialog(hwndDlg,0);
  367. }
  368. }
  369. break;
  370. case WM_UPDATESTATUS:
  371. {
  372. ArtParser * parser = GetParam(hwndDlg);
  373. if(parser)
  374. {
  375. wchar_t s[100] = {0};
  376. if(parser->error) getStringW(IDS_ART_SEARCH_FAILED,s,100);
  377. else if(parser->doneXML) getStringW(IDS_ART_SEARCH_FINISHED,s,100);
  378. else getStringW(IDS_ART_SEARCH_PROGRESS,s,100);
  379. wchar_t buf[512] = {0};
  380. StringCchPrintfW(buf,512,getStringW(IDS_ART_SEARCH_STATUS,0,0),s,parser->numImages,parser->curImage - parser->failedImages,parser->failedImages,parser->numImages - parser->curImage);
  381. SetDlgItemTextW(hwndDlg,IDC_STATUS,buf);
  382. }
  383. }
  384. break;
  385. case WM_TIMER:
  386. {
  387. ArtParser * parser = GetParam(hwndDlg);
  388. switch(wParam)
  389. {
  390. case 0:
  391. if(parser && !parser->run())
  392. KillTimer(hwndDlg,0);
  393. break;
  394. case 1:
  395. if(parser && parser->imgDownload.size())
  396. {
  397. ImgDownloader *d = parser->imgDownload.at(0);
  398. if(d->error)
  399. {
  400. parser->failedImages++;
  401. parser->curImage++;
  402. parser->imgDownload.eraseindex(0);
  403. delete d;
  404. UpdateStatus(hwndDlg);
  405. }
  406. else if(d->done)
  407. {
  408. parser->curImage++;
  409. parser->imgDownload.eraseindex(0);
  410. AddImageToList(m_child,d);
  411. UpdateStatus(hwndDlg);
  412. }
  413. else d->run();
  414. }
  415. if(parser->error || parser->doneXML)
  416. {
  417. if(parser->curImage == parser->numImages)
  418. {
  419. KillTimer(hwndDlg,1);
  420. if(!parser->numImages)
  421. {
  422. wchar_t title[100] = {0};
  423. getStringW(IDS_ART_SEARCH_NOT_FOUND_TITLE,title,100);
  424. MessageBoxW(hwndDlg,getStringW(IDS_ART_SEARCH_NOT_FOUND,0,0),title,0);
  425. //EndDialog(hwndDlg,-1); //CUT, since we have now a custom search
  426. }
  427. EnableWindow(GetDlgItem(hwndDlg, IDC_SEARCHAGAIN), true);
  428. }
  429. }
  430. break;
  431. }
  432. }
  433. break;
  434. case WM_DESTROY:
  435. {
  436. SetWindowLong(hwndDlg,GWLP_USERDATA,0);
  437. }
  438. break;
  439. case WM_CLOSE:
  440. EndDialog(hwndDlg,-1);
  441. break;
  442. case WM_COMMAND:
  443. switch(LOWORD(wParam))
  444. {
  445. case IDCANCEL:
  446. EndDialog(hwndDlg,-1);
  447. break;
  448. case IDC_CANCELALL:
  449. EndDialog(hwndDlg,-2);
  450. break;
  451. case IDC_SEARCHAGAIN: // copy text field params to parser
  452. ArtParser * parser = GetParam(hwndDlg);
  453. // Let the first search process finish
  454. if (!(parser->doneXML || parser->error))
  455. {
  456. //TODO change this string
  457. MessageBoxW(hwndDlg, L"Please wait till the current retrieval is finished", L"", 0);
  458. return 0;
  459. }
  460. GetDlgItemTextW(hwndDlg,IDC_SEARCHREFINE_ALBUM, tmp_album, 512);
  461. GetDlgItemTextW(hwndDlg,IDC_SEARCHREFINE_ARTIST, tmp_artist, 512);
  462. GetDlgItemTextW(hwndDlg,IDC_SEARCHREFINE_YEAR, tmp_year, 5);
  463. // End Dialog w/ returning 2: indicates that teh users wants to start a custom search
  464. EndDialog(hwndDlg,2);
  465. break;
  466. }
  467. break;
  468. }
  469. return 0;
  470. }
  471. // from FileInfo.cpp
  472. extern HBITMAP getBitmap(ARGB32 * data, int dw, int dh, int targetW, int targetH, HWND parent);
  473. extern ARGB32 * decompressImage(const void *data, int datalen, int * dataW, int * dataH);
  474. HBITMAP loadImage(const void * data, int datalen, int w, int h, HWND parent, int *dw=0, int *dh=0)
  475. {
  476. int dataW=0, dataH=0;
  477. ARGB32* ret = decompressImage(data,datalen,&dataW,&dataH);
  478. if(dw) *dw = dataW;
  479. if(dh) *dh = dataH;
  480. if(!ret) return 0;
  481. HBITMAP r = getBitmap(ret, dataW, dataH, w, h, parent);
  482. WASABI_API_MEMMGR->sysFree(ret);
  483. return r;
  484. }
  485. #define GetDlgParent(hwndDlg) GetParent(GetParent(GetParent(hwndDlg)))
  486. static INT_PTR CALLBACK imageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  487. {
  488. switch(uMsg)
  489. {
  490. case WM_INITDIALOG:
  491. {
  492. SetWindowLong(hwndDlg,GWLP_USERDATA,lParam);
  493. ImgDownloader *d = (ImgDownloader *)lParam;
  494. int w=0,h=0;
  495. HBITMAP bm = loadImage(d->imgbuf,d->imgbufused,140,140,hwndDlg,&w,&h);
  496. SendDlgItemMessage(hwndDlg,IDC_IMAGE,STM_SETIMAGE,IMAGE_BITMAP,(LPARAM)bm);
  497. wchar_t buf[1024] = {0};
  498. StringCchPrintfW(buf,1024,L"%s: %dx%d (%d kB)",d->desc,w,h,(d->imgbufused/1024));
  499. SetDlgItemTextW(hwndDlg,IDC_IMGTEXT,buf);
  500. }
  501. break;
  502. case WM_DESTROY:
  503. {
  504. ImgDownloader *d = GetParamC(hwndDlg);
  505. SetWindowLong(hwndDlg,GWLP_USERDATA,0);
  506. if(d) delete d;
  507. HBITMAP bm = (HBITMAP)SendDlgItemMessage(hwndDlg,IDC_IMAGE,STM_SETIMAGE,IMAGE_BITMAP,0);
  508. if(bm) DeleteObject(bm);
  509. }
  510. break;
  511. case WM_COMMAND:
  512. if(LOWORD(wParam) != IDC_SELECT)
  513. break;
  514. // else run through
  515. case WM_LBUTTONDBLCLK:
  516. SendMessageW(GetDlgParent(hwndDlg),WM_SELECTED,(WPARAM)hwndDlg,(LPARAM)GetParamC(hwndDlg));
  517. break;
  518. }
  519. return 0;
  520. }
  521. // scroll shit, nothing interesting is happening down here...
  522. static INT_PTR CALLBACK scrollChildHostProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  523. {
  524. //static HWND m_child;
  525. switch(uMsg)
  526. {
  527. case WM_INITDIALOG:
  528. {
  529. RECT r;
  530. HWND hw = GetParent(hwndDlg);
  531. GetWindowRect(GetDlgItem(hw,IDC_PLACEHOLDER),&r);
  532. ScreenToClient(hw,(LPPOINT)&r);
  533. ScreenToClient(hw,((LPPOINT)&r)+1);
  534. SetWindowPos(hwndDlg,NULL,r.left,r.top,r.right-r.left,r.bottom-r.top,SWP_NOZORDER|SWP_NOACTIVATE);
  535. LPCreateDialogW(IDD_ARTDOWNLOADER_SCROLLCHILD,hwndDlg,(WNDPROC)scrollChildProc);
  536. SCROLLINFO si={sizeof(si),SIF_RANGE|SIF_PAGE,0};
  537. si.nPage = (r.right - r.left);
  538. SetScrollInfo(hwndDlg,SB_HORZ,&si,TRUE);
  539. }
  540. break;
  541. case WM_ADDCHILD:
  542. {
  543. HWND m_child = GetWindow(hwndDlg,GW_CHILD);
  544. HWND newChild = (HWND)SendMessageW(m_child,uMsg,wParam,lParam);
  545. RECT r,r2;
  546. GetClientRect(m_child,&r);
  547. GetClientRect(hwndDlg,&r2);
  548. SCROLLINFO si={sizeof(si),SIF_RANGE|SIF_PAGE,0};
  549. si.nMin = 0;
  550. si.nMax = (r.right - r.left);
  551. si.nPage = (r2.right - r2.left);
  552. if(si.nMax < 0) si.nMax = 0;
  553. SetScrollInfo(hwndDlg,SB_HORZ,&si,TRUE);
  554. return (INT_PTR)newChild;
  555. }
  556. break;
  557. case WM_HSCROLL:
  558. {
  559. HWND m_child = GetWindow(hwndDlg,GW_CHILD);
  560. int v=0;
  561. RECT r;
  562. RECT r2;
  563. GetClientRect(hwndDlg,&r2);
  564. GetClientRect(m_child,&r);
  565. int action = LOWORD(wParam);
  566. if (r2.right < r.right) {
  567. if (action == SB_THUMBPOSITION || action == SB_THUMBTRACK) {
  568. SCROLLINFO si={sizeof(si),SIF_TRACKPOS|SIF_POS};
  569. GetScrollInfo(hwndDlg,SB_HORZ,&si);
  570. v=si.nTrackPos;
  571. }
  572. else if (action == SB_TOP)
  573. v=0;
  574. else if (action == SB_BOTTOM)
  575. v=r.right-r2.right;
  576. else if (action == SB_PAGEDOWN || action == SB_LINEDOWN) {
  577. SCROLLINFO si={sizeof(si),SIF_TRACKPOS|SIF_POS};
  578. GetScrollInfo(hwndDlg,SB_HORZ,&si);
  579. if(action == SB_LINEDOWN)
  580. v=si.nPos + (r2.right)/10;
  581. else
  582. v=si.nPos + r2.right;
  583. if (v > r.right-r2.right) v=r.right-r2.right;
  584. }
  585. else if (action == SB_PAGEUP || action == SB_LINEUP) {
  586. SCROLLINFO si={sizeof(si),SIF_TRACKPOS|SIF_POS};
  587. GetScrollInfo(hwndDlg,SB_HORZ,&si);
  588. if(action == SB_LINEUP)
  589. v=si.nPos - (r2.right)/10;
  590. else
  591. v=si.nPos - r2.right;
  592. if (v < 0) v=0;
  593. }
  594. else return 0;
  595. SetScrollPos(hwndDlg,SB_HORZ,v,!(action == SB_THUMBPOSITION || action == SB_THUMBTRACK));
  596. SetWindowPos(m_child,NULL,0-v,0,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  597. }
  598. else {
  599. SetScrollPos(hwndDlg,SB_HORZ,0,!(action == SB_THUMBPOSITION || action == SB_THUMBTRACK));
  600. SetWindowPos(m_child,NULL,0,0,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  601. }
  602. }
  603. break;
  604. }
  605. return 0;
  606. }
  607. static INT_PTR CALLBACK scrollChildProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  608. {
  609. switch(uMsg)
  610. {
  611. case WM_INITDIALOG:
  612. {
  613. RECT r;
  614. GetClientRect(hwndDlg,&r);
  615. SetWindowPos(hwndDlg,0,0,0,0,r.bottom,SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
  616. }
  617. break;
  618. case WM_ADDCHILD:
  619. {
  620. HWND newChild = LPCreateDialogParamW(IDD_ARTDOWNLOADER_IMAGE,hwndDlg,imageProc,lParam);
  621. RECT r,r2;
  622. GetClientRect(hwndDlg,&r);
  623. GetClientRect(newChild,&r2);
  624. SetWindowPos(hwndDlg,0,0,0,r.right + r2.right,r.bottom,SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
  625. SetWindowPos(newChild,0,r.right,0,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  626. ShowWindow(newChild,SW_SHOWNA);
  627. return (INT_PTR)newChild;
  628. }
  629. break;
  630. }
  631. return 0;
  632. }
  633. #endif