ABOUT.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author:
  6. ** Created:
  7. **/
  8. #include "Main.h"
  9. #include "language.h"
  10. #include <math.h>
  11. #include "../nu/threadname.h"
  12. #include "resource.h"
  13. #include <tataki/export.h>
  14. #include "api.h"
  15. #include "../nu/threadpool/TimerHandle.hpp"
  16. #include "../nu/AutoWide.h"
  17. int img_w[2] = {400, 100}, img_h[2] = {189, 34};
  18. int about_lastpage;
  19. HWND about_hwnd;
  20. #define M_PI 3.14159265358979323846
  21. static BOOL CALLBACK tipsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  22. static BOOL CALLBACK whatsnewProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  23. static BOOL CALLBACK about1Proc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  24. static BOOL CALLBACK creditProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  25. static BOOL CALLBACK translationProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  26. static LRESULT WINAPI aboutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  27. static unsigned const char sq_table[]=
  28. {0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61, 64, 65,
  29. 67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89, 90, 91, 93, 94,
  30. 96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113,
  31. 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 128,
  32. 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
  33. 142, 143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153,
  34. 154, 155, 155, 156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164,
  35. 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175,
  36. 176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 183, 184, 185,
  37. 185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 193, 194,
  38. 195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 203, 203,
  39. 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, 212,
  40. 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220,
  41. 221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228,
  42. 229, 229, 230, 230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236,
  43. 236, 237, 237, 238, 238, 239, 240, 240, 241, 241, 242, 242, 243, 243,
  44. 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250,
  45. 251, 251, 252, 252, 253, 253, 254, 254, 255};
  46. static __inline unsigned long isqrt(unsigned long n)
  47. {
  48. if (n >= 0x10000)
  49. if (n >= 0x1000000)
  50. if (n >= 0x10000000)
  51. if (n >= 0x40000000) return(sq_table[n >> 24] << 8);
  52. else return(sq_table[n >> 22] << 7);
  53. else
  54. if (n >= 0x4000000) return(sq_table[n >> 20] << 6);
  55. else return(sq_table[n >> 18] << 5);
  56. else
  57. if (n >= 0x100000)
  58. if (n >= 0x400000) return(sq_table[n >> 16] << 4);
  59. else return(sq_table[n >> 14] << 3);
  60. else
  61. if (n >= 0x40000) return(sq_table[n >> 12] << 2);
  62. else return(sq_table[n >> 10] << 1);
  63. else
  64. if (n >= 0x100)
  65. if (n >= 0x1000)
  66. if (n >= 0x4000) return(sq_table[n >> 8]);
  67. else return(sq_table[n >> 6] >> 1);
  68. else
  69. if (n >= 0x400) return(sq_table[n >> 4] >> 2);
  70. else return(sq_table[n >> 2] >> 3);
  71. else
  72. if (n >= 0x10)
  73. if (n >= 0x40) return(sq_table[n] >> 4);
  74. else return(sq_table[n << 2] << 5);
  75. else
  76. if (n >= 0x4) return(sq_table[n >> 4] << 6);
  77. else return(sq_table[n >> 6] << 7);
  78. }
  79. void about_dialog(void)
  80. {
  81. if (about_hwnd)
  82. {
  83. SetForegroundWindow(about_hwnd);
  84. return;
  85. }
  86. about_hwnd=(HWND)LPCreateDialogW(IDD_NEWABOUT, hMainWindow, aboutProc);
  87. // show about window and restore last position as applicable
  88. POINT pt = {about_rect.left, about_rect.top};
  89. if (!windowOffScreen(about_hwnd, pt))
  90. SetWindowPos(about_hwnd, HWND_TOP, about_rect.left, about_rect.top, 0, 0, SWP_NOSIZE | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
  91. else
  92. ShowWindow(about_hwnd, SW_SHOW);
  93. }
  94. static LRESULT WINAPI aboutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  95. {
  96. static HWND cur_wnd;
  97. switch (uMsg)
  98. {
  99. case WM_INITDIALOG:
  100. {
  101. int t=about_lastpage;
  102. about_lastpage=-1;
  103. // make sure not to show the localised page if not under a language pack
  104. if (t==4 && config_langpack[0]) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON2, 0);
  105. else if (t==3) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON6, 0);
  106. else if (t==2) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON5, 0);
  107. else if (t==1) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON4, 0);
  108. else
  109. {
  110. if (t==4) t = 0;
  111. SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON3, 0);
  112. }
  113. }
  114. return FALSE;
  115. case WM_COMMAND:
  116. switch (LOWORD(wParam))
  117. {
  118. case IDCANCEL:
  119. case IDOK:
  120. DestroyWindow(hwndDlg);
  121. return FALSE;
  122. case IDC_BUTTON3:
  123. case IDC_BUTTON4:
  124. case IDC_BUTTON5:
  125. case IDC_BUTTON6:
  126. case IDC_BUTTON2:
  127. {
  128. int id=-1;
  129. int t = 0;
  130. void *proc = 0;
  131. if (LOWORD(wParam)==IDC_BUTTON3) t=0;
  132. if (LOWORD(wParam)==IDC_BUTTON4) t=1;
  133. if (LOWORD(wParam)==IDC_BUTTON5) t=2;
  134. if (LOWORD(wParam)==IDC_BUTTON6) t=3;
  135. if (LOWORD(wParam)==IDC_BUTTON2) t=4;
  136. if (t == about_lastpage) return 0;
  137. about_lastpage=t;
  138. switch (t)
  139. {
  140. case 0: id=IDD_NEWABOUT1; proc=about1Proc; break;
  141. case 1: id=IDD_NEWABOUT2; proc=creditProc; break;
  142. case 2: id=IDD_NEWABOUT3; proc=tipsProc; break;
  143. case 3: id=IDD_NEWABOUT4; proc=whatsnewProc; break;
  144. case 4: id=IDD_ABOUT_TRANSLATION; proc=translationProc; break;
  145. }
  146. if (IsWindow(cur_wnd))
  147. {
  148. DestroyWindow(cur_wnd);
  149. cur_wnd=0;
  150. }
  151. if (id != -1)
  152. {
  153. cur_wnd = CreateDialogW(language_pack_instance, MAKEINTRESOURCEW(id), hwndDlg, (DLGPROC)proc);
  154. // handles cases where there's no localised info page in a language pack / under en-us
  155. if(!IsWindow(cur_wnd)) cur_wnd = LPCreateDialogW(id, hwndDlg, (DLGPROC)proc);
  156. {
  157. RECT r;
  158. GetWindowRect(GetDlgItem(hwndDlg,IDC_RECT),&r);
  159. ScreenToClient(hwndDlg,(LPPOINT)&r);
  160. SetWindowPos(cur_wnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
  161. }
  162. ShowWindow(cur_wnd,SW_SHOWNA);
  163. {
  164. RECT r,r2;
  165. GetWindowRect(GetDlgItem(hwndDlg,IDC_BUTTON3),&r);
  166. GetWindowRect(GetDlgItem(hwndDlg,IDC_BUTTON6),&r2);
  167. r.right=r2.right;
  168. ScreenToClient(hwndDlg,(LPPOINT)&r);
  169. ScreenToClient(hwndDlg,((LPPOINT)&r)+1);
  170. InvalidateRect(hwndDlg,&r,FALSE);
  171. }
  172. }
  173. }
  174. return FALSE;
  175. }
  176. break;
  177. case WM_DESTROY:
  178. GetWindowRect(hwndDlg, &about_rect);
  179. if (IsWindow(cur_wnd)) DestroyWindow(cur_wnd);
  180. cur_wnd=0;
  181. about_hwnd=NULL;
  182. break;
  183. }
  184. if (uMsg == WM_DRAWITEM)
  185. {
  186. DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam;
  187. if (di->CtlType == ODT_BUTTON)
  188. {
  189. wchar_t wt[123] = {0};
  190. int sel=0;
  191. RECT r;
  192. GetDlgItemTextW(hwndDlg,wParam,wt,123);
  193. if (di->CtlID==IDC_BUTTON3 && about_lastpage==0) sel=1;
  194. else if (di->CtlID==IDC_BUTTON4 && about_lastpage==1) sel=1;
  195. else if (di->CtlID==IDC_BUTTON5 && about_lastpage==2) sel=1;
  196. else if (di->CtlID==IDC_BUTTON6 && about_lastpage==3) sel=1;
  197. else if (di->CtlID==IDC_BUTTON2 && about_lastpage==4) sel=1;
  198. if (di->CtlID != IDC_BUTTON6)
  199. {
  200. MoveToEx(di->hDC,di->rcItem.right-1,di->rcItem.top,NULL);
  201. LineTo(di->hDC,di->rcItem.right-1,di->rcItem.bottom);
  202. }
  203. // draw text
  204. if (!sel && (di->itemState & (ODS_SELECTED)))
  205. SetTextColor(di->hDC,RGB(0,40,255));
  206. r=di->rcItem;
  207. DrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER);
  208. if (sel)
  209. {
  210. r=di->rcItem;
  211. r.left+=2;
  212. SetBkMode(di->hDC,TRANSPARENT);
  213. DrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER);
  214. }
  215. }
  216. }
  217. return 0;
  218. }
  219. /* Window Proc for the 'keyboard shorcuts' tab of about screen */
  220. static BOOL CALLBACK tipsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  221. {
  222. static HGLOBAL hResource=0;
  223. static DWORD hResourceSize=0;
  224. switch (uMsg)
  225. {
  226. case WM_INITDIALOG:
  227. {
  228. char *b = NULL, *p = 0, *op = 0;
  229. DWORD size = 0;
  230. if (!hResource)
  231. {
  232. hResource = langManager->LoadResourceFromFileW(language_pack_instance, hMainInstance,TEXT("TEXT"), TEXT("TIPSTEXT"),&size);
  233. hResourceSize = size;
  234. }
  235. p = (char*)hResource;
  236. if (p && (op = strstr(p, "!!End"))) // if there's "!!End" in the resource, than copy everything before it
  237. {
  238. b = (char*)GlobalAlloc(GPTR, op-p+1);
  239. memcpy(b, p, op-p);
  240. b[op-p] = 0;
  241. } else {
  242. b = (char*)GlobalAlloc(GPTR, hResourceSize+1);
  243. memcpy(b, p, hResourceSize);
  244. b[hResourceSize] = 0;
  245. }
  246. SetDlgItemTextA(hwndDlg, IDC_TIPS, (b ? b : p)); // send it to the text control to display
  247. if (b) GlobalFree(b);
  248. }
  249. break;
  250. case WM_COMMAND:
  251. if(LOWORD(wParam) == IDCANCEL)
  252. {
  253. DestroyWindow(about_hwnd);
  254. }
  255. break;
  256. }
  257. if (FALSE != IsDirectMouseWheelMessage(uMsg))
  258. {
  259. HWND textWindow;
  260. RECT windowRect;
  261. textWindow = GetDlgItem(hwndDlg, IDC_TIPS);
  262. if (NULL != textWindow &&
  263. FALSE != GetClientRect(textWindow, &windowRect))
  264. {
  265. POINT pt;
  266. POINTSTOPOINT(pt, lParam);
  267. MapWindowPoints(HWND_DESKTOP, textWindow, &pt, 1);
  268. if (FALSE != PtInRect(&windowRect, pt))
  269. {
  270. SendMessageW(textWindow, WM_MOUSEWHEEL, wParam, lParam);
  271. SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
  272. }
  273. return TRUE;
  274. }
  275. }
  276. return 0;
  277. }
  278. WNDPROC whatedproc = 0;
  279. static LRESULT CALLBACK whatseditproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  280. {
  281. if(uMsg == WM_KEYDOWN)
  282. {
  283. if(wParam == 'F' && (GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_SHIFT)&0x8000))
  284. {
  285. if(IsWindowEnabled(GetDlgItem(GetParent(hwndDlg), IDC_ABOUT_SEARCH)))
  286. {
  287. SendMessageW(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(IDC_ABOUT_SEARCH,0), 0);
  288. }
  289. }
  290. }
  291. return CallWindowProcW(whatedproc,hwndDlg,uMsg,wParam,lParam);
  292. }
  293. #define WHATSNEW_BUFFER_SIZE 262144
  294. static wchar_t* ver_buf;
  295. void GetWhatsNewFromFile(FILE *fp)
  296. {
  297. bool utf8=false, utf16=false;
  298. unsigned char BOM[3] = {0, 0, 0};
  299. if (fread(BOM, 3, 1, fp) == 1 && BOM[0] == 0xEF && BOM[1] == 0xBB && BOM[2] == 0xBF)
  300. utf8 = true;
  301. else
  302. {
  303. fseek(fp, 0, SEEK_SET);
  304. if (fread(BOM, 2, 1, fp) == 1 && BOM[0] == 0xFF && BOM[1] == 0xFE)
  305. utf16=true;
  306. else
  307. fseek(fp, 0, SEEK_SET);
  308. }
  309. if (utf16)
  310. {
  311. wchar_t buffer[WHATSNEW_BUFFER_SIZE]={0}, *p=buffer;
  312. for (;;)
  313. {
  314. fgetws(p,1024,fp);
  315. if (feof(fp)) break;
  316. if (p[wcslen(p)-1]==L'\n')
  317. p[wcslen(p)-1]=0;
  318. StringCchCatW(p,WHATSNEW_BUFFER_SIZE,L"\r\n");
  319. p=p+wcslen(p);
  320. if (p-buffer > WHATSNEW_BUFFER_SIZE) break;
  321. }
  322. ver_buf = wcsdup(buffer);
  323. }
  324. else
  325. {
  326. char buffer[WHATSNEW_BUFFER_SIZE]={0},*p=buffer;
  327. for (;;)
  328. {
  329. fgets(p,1024,fp);
  330. if (feof(fp)) break;
  331. if (p[lstrlenA(p)-1]=='\n')
  332. p[lstrlenA(p)-1]=0;
  333. StringCchCatA(p,WHATSNEW_BUFFER_SIZE,"\r\n");
  334. p=p+lstrlenA(p);
  335. if (p-buffer > WHATSNEW_BUFFER_SIZE) break;
  336. }
  337. if (utf8)
  338. {
  339. ver_buf = AutoWideDup(buffer, CP_UTF8);
  340. }
  341. else
  342. {
  343. ver_buf = AutoWideDup(buffer);
  344. }
  345. }
  346. }
  347. static std::map<int,wchar_t*> versions;
  348. /* Window Proc for the 'version history' tab of about screen */
  349. static BOOL CALLBACK whatsnewProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  350. {
  351. static UINT fm_msg;
  352. static FINDREPLACEW find;
  353. static wchar_t fromstring[256];
  354. static HWND finder;
  355. if(uMsg == fm_msg)
  356. {
  357. LPFINDREPLACEW lpFindReplace = (LPFINDREPLACEW) lParam;
  358. if(lpFindReplace->Flags & FR_FINDNEXT)
  359. {
  360. int len = GetWindowTextLengthW(GetDlgItem(hwndDlg,IDC_TIPS))+1,
  361. flen = lstrlenW(lpFindReplace->lpstrFindWhat), start = 0, end = 0;
  362. wchar_t *buffer = (wchar_t*)calloc((len+1),sizeof(wchar_t)),
  363. *search = (wchar_t*)calloc((flen+2),sizeof(wchar_t)),
  364. *result = 0;
  365. lstrcpynW(search,lpFindReplace->lpstrFindWhat,flen+1);
  366. SendDlgItemMessageW(hwndDlg,IDC_TIPS,EM_GETSEL,(WPARAM)&start,(LPARAM)&end);
  367. GetDlgItemTextW(hwndDlg,IDC_TIPS,buffer,len);
  368. // handles the match case option
  369. if(!(lpFindReplace->Flags & FR_MATCHCASE))
  370. {
  371. CharUpperBuffW(buffer, len);
  372. CharUpperBuffW(search, flen+1);
  373. }
  374. if((result = wcsstr(buffer+end,search)))
  375. {
  376. SendDlgItemMessage(hwndDlg,IDC_TIPS,EM_SETSEL,result-buffer,(result-buffer)+flen);
  377. SendDlgItemMessage(hwndDlg,IDC_TIPS,EM_SCROLLCARET,0,0);
  378. }
  379. else
  380. {
  381. MessageBoxW(finder,getStringW(IDS_NO_MATCHES_FOUND,NULL,0),L"Winamp",MB_ICONINFORMATION);
  382. }
  383. free(buffer);
  384. free(search);
  385. }
  386. }
  387. switch (uMsg) {
  388. case WM_INITDIALOG:
  389. {
  390. wchar_t fn[MAX_PATH] = {0};
  391. FILE *fp = NULL;
  392. int last_add = 0;
  393. whatedproc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwndDlg,IDC_TIPS),GWLP_WNDPROC,(LONG_PTR)whatseditproc);
  394. SendDlgItemMessage(hwndDlg, IDC_TIPS, EM_SETLIMITTEXT, 0, 0);
  395. // attempt to pull a localised whatsnew.txt
  396. // before reverting to the english default
  397. if (lang_directory[0])
  398. {
  399. lstrcpynW(fn,lang_directory,MAX_PATH);
  400. }
  401. else
  402. {
  403. GetModuleFileNameW(NULL,fn,MAX_PATH);
  404. PathRemoveFileSpecW(fn);
  405. }
  406. PathAppendW(fn, L"whatsnew.txt");
  407. // we don't set the buffer position so that it all works on the fallback code
  408. // and make sure there's a selection no matter what happens with other things
  409. SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_ADDSTRING,0,(LPARAM)getStringW(IDS_SHOW_ALL_HISTORY,NULL,0));
  410. SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_SETCURSEL,0,0);
  411. versions.clear();
  412. fp = _wfopen(fn,L"rb");
  413. // if there isn't a localised whatsnew.txt then revert to the old ways
  414. if(!fp)
  415. {
  416. GetModuleFileNameW(NULL,fn,MAX_PATH);
  417. PathRemoveFileSpecW(fn);
  418. PathAppendW(fn,L"whatsnew.txt");
  419. fp = _wfopen(fn,L"rb");
  420. }
  421. if (fp)
  422. {
  423. GetWhatsNewFromFile(fp);
  424. fclose(fp);
  425. wchar_t* p = ver_buf;
  426. while(p && *p)
  427. {
  428. // populate the version combobox
  429. if(!wcsncmp(p,L"Winamp 5.",9))
  430. {
  431. wchar_t* pp = p, ver[64] = {0};
  432. while(pp && *pp && *pp != L'\r') pp = CharNextW(pp);
  433. // need to make sure that we've actually found a valid part otherwise
  434. // just skip over things and don't fill in the combobox (attempted exploit)
  435. if(pp && *pp && *pp == L'\r'){
  436. pp = CharNextW(pp);
  437. // make sure that we keep within the buffer size as some people have
  438. // tried to make a buffer overflow vulnerability with this on XP SP3
  439. lstrcpynW(ver,p,(pp-p<64?pp-p:64));
  440. wchar_t* v = ver, *vn = 0, *vne = 0;
  441. while(v && *v && *v != L'\t') v = CharNextW(v);
  442. if(v && *v == L'\t'){
  443. vn = vne = CharNextW(v);
  444. *v = 0;
  445. if(vn && *vn == L'[') vn = CharNextW(vn);
  446. while(vne && *vne && *vne != L']') vne = CharNextW(vne);
  447. if(vne && *vne == L']') *vne = 0;
  448. }
  449. last_add = SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_ADDSTRING,0,(LPARAM)ver);
  450. SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_SETITEMDATA,last_add,(LPARAM)p);
  451. versions[last_add] = wcsdup(vn);
  452. }
  453. }
  454. p = CharNextW(p);
  455. }
  456. // reset the selection to the last view and force an update to that
  457. // would be better to do it straight away on load but this ensures all synchs up
  458. SendDlgItemMessage(hwndDlg,IDC_VER_COMBO,CB_SETCURSEL,_r_i("whtsnewlp",1),0);
  459. SendMessageW(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_VER_COMBO,CBN_SELCHANGE),(LPARAM)GetDlgItem(hwndDlg,IDC_VER_COMBO));
  460. }
  461. else
  462. {
  463. EnableWindow(GetDlgItem(hwndDlg,IDC_VER_COMBO),0);
  464. EnableWindow(GetDlgItem(hwndDlg,IDC_ABOUT_SEARCH),0);
  465. SetDlgItemTextW(hwndDlg,IDC_TIPS,getStringW(IDS_WHATSNEW_FAIL,ver_buf,WHATSNEW_BUFFER_SIZE));
  466. }
  467. }
  468. return FALSE;
  469. case WM_COMMAND:
  470. if(LOWORD(wParam) == IDC_VER_COMBO && HIWORD(wParam) == CBN_SELCHANGE)
  471. {
  472. int cur = SendMessageW((HWND)lParam,CB_GETCURSEL,0,0);
  473. wchar_t* position = (wchar_t*)SendMessageW((HWND)lParam,CB_GETITEMDATA,cur,0);
  474. if(cur != CB_ERR && position){
  475. wchar_t* p = position, *out_buf = (wchar_t*)calloc(WHATSNEW_BUFFER_SIZE,sizeof(wchar_t)), *out = out_buf;
  476. while(p && *p)
  477. {
  478. if(*p == L'\t')
  479. {
  480. if(*CharNextW(p) == L'[')
  481. {
  482. wchar_t* pb = p;
  483. while(pb && *pb && *pb != L']')
  484. {
  485. pb = CharNextW(pb);
  486. }
  487. if(pb && *pb == L']') p = CharNextW(pb);
  488. }
  489. }
  490. // look for 2 empty lines to indicate end of version block
  491. if(*p == L'\r')
  492. {
  493. wchar_t* n = CharNextW(p);
  494. if(n && *n == L'\n')
  495. {
  496. n = CharNextW(n);
  497. if(n && *n == L'\r')
  498. {
  499. break;
  500. }
  501. }
  502. }
  503. *out = *p;
  504. p = CharNextW(p);
  505. out = CharNextW(out);
  506. }
  507. *out = 0;
  508. wchar_t released[128] = {0};
  509. if(cur == 1 || cur > 1 && versions[cur] != 0)
  510. StringCchPrintfW(released,128,getStringW(IDS_RELEASED,NULL,0), (cur == 1 ? AutoWide(__DATE__) : versions[cur]));
  511. else
  512. released[0] = 0;
  513. SendMessageW(GetDlgItem(hwndDlg,IDC_RELEASED),WM_SETTEXT,0,(LPARAM)released);
  514. SendMessageW(GetDlgItem(hwndDlg,IDC_TIPS),WM_SETTEXT,0,(LPARAM)out_buf);
  515. free(out_buf);
  516. }
  517. else{
  518. SendMessageW(GetDlgItem(hwndDlg,IDC_RELEASED),WM_SETTEXT,0,(LPARAM)L"");
  519. SendMessageW(GetDlgItem(hwndDlg,IDC_TIPS),WM_SETTEXT,0,(LPARAM)ver_buf);
  520. }
  521. }
  522. else if(LOWORD(wParam) == IDC_ABOUT_SEARCH)
  523. {
  524. if(!IsWindow(finder))
  525. {
  526. if(!fm_msg) fm_msg = RegisterWindowMessageW(FINDMSGSTRINGW);
  527. find.lStructSize = sizeof(find);
  528. find.hwndOwner = hwndDlg;
  529. find.Flags = FR_DOWN|FR_HIDEWHOLEWORD|FR_HIDEUPDOWN;
  530. find.lpstrFindWhat = fromstring;
  531. find.wFindWhatLen = ARRAYSIZE(fromstring);
  532. finder = FindTextW(&find);
  533. ShowWindow(finder,SW_SHOW);
  534. }
  535. else
  536. {
  537. SetActiveWindow(finder);
  538. }
  539. }
  540. else if(LOWORD(wParam) == IDCANCEL)
  541. {
  542. DestroyWindow(about_hwnd);
  543. }
  544. break;
  545. case WM_DESTROY:
  546. free(ver_buf);
  547. ver_buf = 0;
  548. //for (int i=0; i!=versions.size(); i++)
  549. // free(versions[i]);
  550. for (auto& version : versions)
  551. {
  552. if (version.second)
  553. {
  554. free(version.second);
  555. }
  556. }
  557. versions.clear();
  558. _w_i("whtsnewlp",SendDlgItemMessage(hwndDlg,IDC_VER_COMBO,CB_GETCURSEL,0,0));
  559. if(IsWindow(finder)) DestroyWindow(finder);
  560. break;
  561. }
  562. if (FALSE != IsDirectMouseWheelMessage(uMsg))
  563. {
  564. HWND textWindow;
  565. RECT windowRect;
  566. textWindow = GetDlgItem(hwndDlg, IDC_TIPS);
  567. if (NULL != textWindow &&
  568. FALSE != GetClientRect(textWindow, &windowRect))
  569. {
  570. POINT pt;
  571. POINTSTOPOINT(pt, lParam);
  572. MapWindowPoints(HWND_DESKTOP, textWindow, &pt, 1);
  573. if (FALSE != PtInRect(&windowRect, pt))
  574. {
  575. SendMessageW(textWindow, WM_MOUSEWHEEL, wParam, lParam);
  576. SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE);
  577. }
  578. return TRUE;
  579. }
  580. }
  581. return 0;
  582. }
  583. static volatile int aboutThread_kill, aboutThread_mode;
  584. static HPALETTE m_haboutpal;
  585. /* This does the 'zooming' effect on the image in the 'winamp' tab of the about screen */
  586. class AboutContext
  587. {
  588. public:
  589. bool Init(HWND _hwndDlg);
  590. bool Tick();
  591. void Quit();
  592. private:
  593. int mode;
  594. static int m_wt,m_wait;
  595. static int a;
  596. HDC m_hdc;
  597. HBITMAP m_hbm,m_oldhbm;
  598. int m_pitch,m_height;
  599. char *m_source,*m_dib;
  600. int m_wmul[200];
  601. RECT r;
  602. HBITMAP m_imgbm, m_imgoldbm;
  603. HDC m_imgdc;
  604. struct
  605. {
  606. BITMAPINFO bmi;
  607. RGBQUAD more_bmiColors[256];
  608. LPVOID data;
  609. } m_bitmap;
  610. int c,use_palette;
  611. HWND hwndDlg;
  612. };
  613. int AboutContext::m_wt = 0;
  614. int AboutContext::m_wait = 0;
  615. int AboutContext::a = 0;
  616. bool AboutContext::Init(HWND _hwndDlg)
  617. {
  618. hwndDlg = _hwndDlg;
  619. mode=(GetAsyncKeyState(VK_SHIFT)&0x8000);
  620. GetClientRect(GetDlgItem(hwndDlg,IDC_ABOUTIMG),&r);
  621. HDC hdc=GetWindowDC(hwndDlg);
  622. if (!hdc)
  623. return false;
  624. use_palette = (GetDeviceCaps(hdc,RASTERCAPS)&RC_PALETTE)?1:0;
  625. m_hdc = CreateCompatibleDC(NULL);
  626. m_imgdc = CreateCompatibleDC(NULL);
  627. ReleaseDC(hwndDlg,hdc);
  628. if (!m_imgdc)
  629. return false;
  630. m_imgbm= (HBITMAP)LoadImage(hMainInstance,MAKEINTRESOURCE((!aboutThread_mode ? IDB_SPLASH : IDB_PLATE)),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
  631. m_imgoldbm=(HBITMAP)SelectObject(m_imgdc,m_imgbm);
  632. m_source=(char *)GlobalAlloc(GPTR,img_w[aboutThread_mode]*img_h[aboutThread_mode]);
  633. if (m_imgbm && m_source)
  634. {
  635. memset(&m_bitmap, 0, sizeof(m_bitmap));
  636. m_bitmap.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  637. m_bitmap.bmi.bmiHeader.biPlanes = 1;
  638. m_bitmap.bmi.bmiHeader.biBitCount = 8;
  639. m_bitmap.bmi.bmiHeader.biCompression = BI_RGB;
  640. m_bitmap.bmi.bmiHeader.biSizeImage = 0;
  641. m_bitmap.bmi.bmiHeader.biClrUsed = 128;
  642. m_bitmap.bmi.bmiHeader.biClrImportant = 128;
  643. m_bitmap.bmi.bmiHeader.biWidth = img_w[aboutThread_mode];
  644. m_bitmap.bmi.bmiHeader.biHeight = -img_h[aboutThread_mode];
  645. m_bitmap.bmi.bmiHeader.biSizeImage = img_w[aboutThread_mode]*img_h[aboutThread_mode];
  646. GetDIBits(m_imgdc,m_imgbm,0,img_h[aboutThread_mode],m_source,(BITMAPINFO *)&m_bitmap,DIB_RGB_COLORS);
  647. GetDIBColorTable(m_imgdc,0,256,m_bitmap.bmi.bmiColors);
  648. SelectObject(m_imgdc, m_imgoldbm);
  649. DeleteDC(m_imgdc);
  650. DeleteObject(m_imgbm);
  651. }
  652. else
  653. {
  654. DeleteDC(m_imgdc);
  655. if (m_imgbm) DeleteObject(m_imgbm);
  656. if (m_source) GlobalFree(m_source);
  657. return false;
  658. }
  659. if (use_palette)
  660. {
  661. struct
  662. {
  663. LOGPALETTE logpal;
  664. PALETTEENTRY palentries[255];
  665. } palette;
  666. palette.logpal.palVersion = 0x300;
  667. palette.logpal.palNumEntries = 128;
  668. for (c = 0; c < 128; c ++)
  669. {
  670. palette.logpal.palPalEntry[c].peRed = m_bitmap.bmi.bmiColors[c].rgbRed;
  671. palette.logpal.palPalEntry[c].peGreen = m_bitmap.bmi.bmiColors[c].rgbGreen;
  672. palette.logpal.palPalEntry[c].peBlue = m_bitmap.bmi.bmiColors[c].rgbBlue;
  673. palette.logpal.palPalEntry[c].peFlags = 0;
  674. }
  675. m_haboutpal = CreatePalette((LOGPALETTE *)&palette.logpal);
  676. }
  677. m_pitch=((r.right-r.left+3)&~3);
  678. m_height=r.bottom-r.top;
  679. m_bitmap.bmi.bmiHeader.biSizeImage = 0;
  680. m_bitmap.bmi.bmiHeader.biClrUsed = 0;
  681. m_bitmap.bmi.bmiHeader.biClrImportant = 0;
  682. m_bitmap.bmi.bmiHeader.biWidth = m_pitch;
  683. m_bitmap.bmi.bmiHeader.biHeight = -m_height;
  684. m_bitmap.bmi.bmiHeader.biSizeImage = m_pitch*m_height;
  685. m_hbm = CreateDIBSection(m_hdc,&m_bitmap.bmi,DIB_RGB_COLORS, &m_bitmap.data, NULL, 0);
  686. if (!m_hbm)
  687. {
  688. if (m_imgbm) DeleteObject(m_imgbm);
  689. if (m_source) GlobalFree(m_source);
  690. return 0;
  691. }
  692. m_oldhbm = (HBITMAP) SelectObject(m_hdc, m_hbm);
  693. m_dib=(char*)m_bitmap.data;
  694. {
  695. for (int x = 0; x < img_h[aboutThread_mode]; x ++)
  696. m_wmul[x]=x*img_w[aboutThread_mode];
  697. }
  698. return true;
  699. }
  700. bool AboutContext::Tick()
  701. {
  702. if (aboutThread_kill)
  703. return false;
  704. int tab[512] = {0};
  705. // Sleep(50);
  706. {
  707. int offs;
  708. int x;
  709. double max_d=sqrt((double)((m_pitch*m_pitch+m_height*m_height))/4.0f);
  710. //int imax_d2=(int)(255.0/max_d*256.0);
  711. int imax_d=(int)max_d;
  712. double dpos;
  713. int thiswt=m_wt;
  714. if (thiswt > 63) thiswt = 126-thiswt;
  715. dpos=1.0+sin(thiswt*M_PI/32.0);
  716. if (dpos < 1.0) dpos=0.5+dpos/2.0;
  717. if (thiswt < 32) offs=thiswt*24;
  718. else offs=(64-thiswt)*24;
  719. if (imax_d > 512) return false;
  720. for (x = 0; x < imax_d; x ++)
  721. {
  722. tab[x]=(int) (pow(sin(x/(max_d-1)),dpos)*1.7*256.0*max_d/(x+1)) - offs;
  723. if (tab[x]<0)tab[x]=-tab[x];
  724. }
  725. if (m_wt == 0)
  726. {
  727. if (m_wait++>=40)
  728. {
  729. m_wt++;
  730. }
  731. }
  732. else
  733. {
  734. m_wait=0;
  735. m_wt++;
  736. }
  737. m_wt&=127;
  738. }
  739. {
  740. int xsc=((!aboutThread_mode ? img_w[0]*180 : img_w[1]*360))/m_pitch;
  741. int ysc=((!aboutThread_mode ? img_h[0]*200 : img_h[1]*500))/m_height;
  742. int w2=m_pitch/2;
  743. int h2=m_height/2;
  744. char *out=m_dib;
  745. int y;
  746. if (m_wt)
  747. {
  748. a=!a;
  749. // weird interlace shit
  750. if (a && mode)
  751. {
  752. out+=m_pitch;
  753. }
  754. for (y = -h2+(mode?a:0); y < h2; y ++)
  755. {
  756. int x2=w2*w2+w2+y*y+256;
  757. int dx2=-2*w2;
  758. int yysc=y*ysc;
  759. int xxsc=-w2*xsc;
  760. int x=m_pitch;
  761. while (x--)
  762. {
  763. int qd=tab[isqrt(x2)];
  764. int ow,oh;
  765. x2+=dx2;
  766. dx2+=2;
  767. ow = img_w[aboutThread_mode]/2 + (qd*xxsc)/65536;
  768. xxsc+=xsc;
  769. oh = img_h[aboutThread_mode]/2 + (qd*yysc)/65536;
  770. if (ow < 0) ow=0;
  771. else if (ow >= img_w[aboutThread_mode]) ow=img_w[aboutThread_mode]-1;
  772. if (oh < 0) oh=0;
  773. else if (oh >= img_h[aboutThread_mode]) oh=img_h[aboutThread_mode]-1;
  774. *out++=m_source[ow+m_wmul[oh]];
  775. }
  776. // weird interlace shit
  777. if (mode)
  778. {
  779. y++;
  780. out+=m_pitch;
  781. }
  782. }
  783. }
  784. else // copy, with optional rescale
  785. {
  786. int x;
  787. int skipw=0;
  788. int skiph=0;
  789. int dxp,dyp,xp,yp;
  790. skiph=(m_height-img_h[aboutThread_mode])/2;
  791. skipw=(m_pitch-img_w[aboutThread_mode])/2;
  792. if (skipw <0) skipw=0;
  793. if (skiph <0) skiph=0;
  794. dxp=(img_w[aboutThread_mode]<<16)/(m_pitch-skipw*2);
  795. dyp=(img_h[aboutThread_mode]<<16)/(m_height-skiph*2);
  796. yp=0;
  797. for (y = 0; y < m_height; y ++)
  798. {
  799. if (y < skiph || y >= m_height - skiph)
  800. {
  801. memset(out,0,m_pitch);
  802. out+=m_pitch;
  803. }
  804. else
  805. {
  806. char *in=m_source+(yp>>16)*img_w[aboutThread_mode];
  807. xp=0;
  808. for (x = 0; x < m_pitch; x ++)
  809. {
  810. if (x < skipw || x >=m_pitch-skipw)
  811. {
  812. *out++=0;
  813. }
  814. else
  815. {
  816. *out++=in[xp>>16];
  817. xp+=dxp;
  818. }
  819. }
  820. yp+=dyp;
  821. }
  822. }
  823. }
  824. }
  825. {
  826. HWND hwnd=GetDlgItem(hwndDlg,IDC_ABOUTIMG);
  827. if (hwnd)
  828. {
  829. HDC h=GetDC(hwnd);
  830. if (h)
  831. {
  832. if (m_haboutpal)
  833. {
  834. SelectPalette(h,m_haboutpal,FALSE);
  835. RealizePalette(h);
  836. }
  837. BitBlt(h,0,0,m_pitch,m_height,m_hdc,0,0,SRCCOPY);
  838. ReleaseDC(hwnd,h);
  839. }
  840. }
  841. }
  842. return true;
  843. }
  844. void AboutContext::Quit()
  845. {
  846. if (m_hbm)
  847. {
  848. if (m_hdc) SelectObject(m_hdc, m_oldhbm);
  849. DeleteObject(m_hbm);
  850. m_hbm = NULL;
  851. m_oldhbm=NULL;
  852. }
  853. if (m_haboutpal)
  854. {
  855. DeleteObject(m_haboutpal);
  856. m_haboutpal = NULL;
  857. }
  858. if (m_hdc)
  859. {
  860. DeleteDC(m_hdc);
  861. m_hdc=NULL;
  862. }
  863. if (m_source)
  864. {
  865. GlobalFree((HGLOBAL)m_source);
  866. m_source=NULL;
  867. }
  868. }
  869. static int AboutTickThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id)
  870. {
  871. AboutContext *context = (AboutContext *)user_data;
  872. TimerHandle t(handle);
  873. if (context->Tick())
  874. {
  875. t.Wait(50);
  876. return 0;
  877. }
  878. else
  879. {
  880. context->Quit();
  881. delete context;
  882. HANDLE event = (HANDLE)id;
  883. SetEvent(event);
  884. WASABI_API_THREADPOOL->RemoveHandle(0, handle);
  885. t.Close();
  886. return 0;
  887. }
  888. }
  889. static int AboutThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id)
  890. {
  891. AboutContext *context = new AboutContext;
  892. if (context->Init((HWND)user_data))
  893. {
  894. TimerHandle t;
  895. WASABI_API_THREADPOOL->AddHandle(0, t, AboutTickThreadPoolFunc, context, id, 0);
  896. t.Wait(50);
  897. }
  898. else
  899. {
  900. delete context;
  901. HANDLE event = (HANDLE)id;
  902. SetEvent(event);
  903. }
  904. return 0;
  905. }
  906. /* Window Proc for the 'winamp' tab of the about screen */
  907. static INT_PTR CALLBACK about1EggProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  908. {
  909. switch(uMsg)
  910. {
  911. case WM_INITDIALOG:
  912. {
  913. #if 0
  914. static char ascii[]="\n\n ______ ____ ___/\\ _/\\_ _____ dro _____ <3 ______ /\\____ _______\n\
  915. \\_ \\/ \\/ \\_\\__/_\\ \\___ _\\ _ \\___ _\\ \\/ \\__\\ _ \\_\n\
  916. / / / / / \\/ |/ \\/ / / / / |/ /\n\
  917. / / / / / / / / / / / / ____/\n\
  918. \\______/\\________\\____/\\____/\\_____\\____/\\_____\\____\\____/\\____/\\____/\n\
  919. _________________________________________________________________ _________\n\
  920. (_________________________________________________________________\\\\\\_WINAMP_)\n\n\n\
  921. supplied by deadbeef\n\n\
  922. cracked by rOn\n\n\
  923. 32kb cool intro by lone";
  924. int i=0;
  925. FILE *fh;
  926. fh=fopen("c:\\blah.c","wt");
  927. for(i=0;ascii[i];i++)
  928. {
  929. ascii[i]^=0x65;
  930. fprintf(fh,"0x%x,",ascii[i]);
  931. if((i&31)==31) fprintf(fh,"\n");
  932. }
  933. fclose(fh);
  934. #else
  935. static char ascii[]={
  936. 0x6f,0x6f,0x6f,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x3a,0x3a,0x3a,0x4a,0x39,0x45,0x45,0x3a,0x4a,0x39,0x3a,0x45,
  937. 0x3a,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x1,0x17,0xa,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x45,0x59,0x56,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x45,0x45,
  938. 0x4a,0x39,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x6f,0x45,0x45,0x39,0x3a,0x45,0x45,0x45,0x45,0x39,0x4a,0x45,0x45,0x45,0x45,0x39,
  939. 0x4a,0x45,0x45,0x45,0x45,0x45,0x39,0x3a,0x39,0x3a,0x3a,0x4a,0x3a,0x39,0x45,0x45,0x45,0x45,0x39,0x3a,0x3a,0x3a,0x45,0x45,0x3a,0x39,0x45,0x45,0x3a,0x45,0x39,0x3a,
  940. 0x3a,0x3a,0x45,0x45,0x3a,0x39,0x45,0x45,0x45,0x45,0x45,0x39,0x4a,0x45,0x45,0x45,0x45,0x45,0x45,0x39,0x3a,0x3a,0x39,0x45,0x45,0x3a,0x45,0x45,0x45,0x39,0x3a,0x6f,
  941. 0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,
  942. 0x45,0x45,0x45,0x45,0x45,0x39,0x4a,0x45,0x45,0x45,0x19,0x4a,0x45,0x45,0x45,0x45,0x45,0x39,0x4a,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x4a,0x45,0x45,0x4a,0x45,0x45,
  943. 0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x19,0x4a,0x45,0x45,0x45,0x45,0x4a,0x6f,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x4a,0x45,0x45,0x4a,0x45,0x45,0x45,
  944. 0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,
  945. 0x4a,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x4a,0x45,0x45,0x45,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x4a,0x6f,0x45,0x45,0x39,
  946. 0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x39,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,0x3a,0x3a,0x3a,
  947. 0x3a,0x3a,0x39,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,0x3a,0x3a,0x3a,0x3a,0x3a,0x39,0x3a,0x3a,0x3a,0x3a,0x39,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,0x3a,0x3a,0x3a,0x3a,0x4a,0x39,
  948. 0x3a,0x3a,0x3a,0x3a,0x4a,0x6f,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,
  949. 0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,
  950. 0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x45,0x45,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x6f,0x45,0x4d,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,
  951. 0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,
  952. 0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x3a,0x39,0x39,0x39,0x3a,0x32,0x2c,0x2b,0x24,
  953. 0x28,0x35,0x3a,0x4c,0x6f,0x6f,0x6f,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,
  954. 0x45,0x45,0x45,0x16,0x10,0x15,0x15,0x9,0xc,0x0,0x1,0x45,0x7,0x1c,0x45,0x1,0x0,0x4,0x1,0x7,0x0,0x0,0x3,0x6f,0x6f,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,
  955. 0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x6,0x17,0x4,0x6,0xe,0x0,0x1,0x45,0x7,0x1c,0x45,
  956. 0x17,0x2a,0xb,0x6f,0x6f,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x45,
  957. 0x56,0x57,0xe,0x7,0x45,0x6,0xa,0xa,0x9,0x45,0xc,0xb,0x11,0x17,0xa,0x45,0x7,0x1c,0x45,0x9,0xa,0xb,0x0,
  958. };
  959. static int dexored=0;
  960. if(!dexored)
  961. {
  962. int i=0;
  963. for(i=0;i<sizeof(ascii);i++) ascii[i]^=0x65;
  964. dexored=1;
  965. }
  966. #endif
  967. SetDlgItemTextA(hwndDlg,IDC_ASCII,ascii);
  968. }
  969. return 1;
  970. case WM_LBUTTONDBLCLK:
  971. {
  972. EndDialog(hwndDlg,0);
  973. ShowWindow(GetDlgItem(GetParent(hwndDlg),IDC_ABOUTIMG),SW_NORMAL);
  974. }
  975. break;
  976. }
  977. return 0;
  978. }
  979. /* Window proc for the about screen (i.e. this one handles the tab changes */
  980. static BOOL CALLBACK about1Proc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  981. {
  982. static HANDLE hThread;
  983. static HWND egg_wnd;
  984. if (uMsg == WM_INITDIALOG)
  985. {
  986. if (!hThread)
  987. {
  988. aboutThread_kill=0;
  989. aboutThread_mode=0;
  990. hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
  991. WASABI_API_THREADPOOL->RunFunction(0, AboutThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, 0);
  992. }
  993. {
  994. wchar_t buf[2048] = {0}, buf2[2048] = {0}, buf3[256] = {0},
  995. *t1 = 0, *t2 = 0, *t3 = 0;
  996. GetDlgItemTextW(hwndDlg,IDC_ABOUTTEXT,buf,ARRAYSIZE(buf));
  997. StringCchPrintfW(buf2,2048,buf,(buf3[0] ? buf3 : (t1 = AutoWideDup(app_version_string))),
  998. (t2 = AutoWideDup(APP_VERSION_PLATFORM)), (t3 = AutoWideDup(app_date)));
  999. SetDlgItemTextW(hwndDlg, IDC_ABOUTTEXT, buf2);
  1000. link_startsubclass(hwndDlg, IDC_WINAMPLINK);
  1001. if (t1) free(t1);
  1002. if (t2) free(t2);
  1003. if (t3) free(t3);
  1004. }
  1005. return TRUE;
  1006. }
  1007. if (uMsg == WM_QUERYNEWPALETTE)
  1008. {
  1009. if (m_haboutpal)
  1010. {
  1011. HDC hdc = GetWindowDC(hwndDlg);
  1012. SelectPalette(hdc,m_haboutpal,FALSE);
  1013. RealizePalette(hdc);
  1014. InvalidateRect(hwndDlg,NULL,FALSE);
  1015. ReleaseDC(hwndDlg,hdc);
  1016. return 1;
  1017. }
  1018. return 0;
  1019. }
  1020. if (uMsg == WM_PALETTECHANGED)
  1021. {
  1022. if (m_haboutpal)
  1023. {
  1024. HDC hdc = GetWindowDC(hwndDlg);
  1025. SelectPalette(hdc,m_haboutpal,FALSE);
  1026. RealizePalette(hdc);
  1027. UpdateColors(hdc);
  1028. ReleaseDC(hwndDlg,hdc);
  1029. return 1;
  1030. }
  1031. return 0;
  1032. }
  1033. if (uMsg == WM_DESTROY)
  1034. {
  1035. if (hThread)
  1036. {
  1037. aboutThread_kill=1;
  1038. WaitForSingleObject(hThread,INFINITE);
  1039. CloseHandle(hThread);
  1040. hThread=NULL;
  1041. }
  1042. }
  1043. if (uMsg == WM_COMMAND)
  1044. {
  1045. switch (LOWORD(wParam))
  1046. {
  1047. case IDC_WINAMPLINK:
  1048. {
  1049. wchar_t homepage[1024] = {0};
  1050. if (config_langpack[0])
  1051. {
  1052. getStringW(IDS_LOCALIZED_HOMEPAGE, homepage, 1024);
  1053. }
  1054. if (homepage[0])
  1055. myOpenURL(hwndDlg, homepage);
  1056. else
  1057. myOpenURL(hwndDlg,L"http://www.winamp.com/");
  1058. }
  1059. return 0;
  1060. }
  1061. }
  1062. if (uMsg == WM_LBUTTONDBLCLK)
  1063. {
  1064. if ((GetAsyncKeyState(VK_SHIFT)&0x8000) && !(GetAsyncKeyState(VK_CONTROL)&0x8000))
  1065. {
  1066. ShowWindow(GetDlgItem(hwndDlg,IDC_ABOUTIMG),SW_HIDE);
  1067. if (!IsWindow(egg_wnd))
  1068. {
  1069. egg_wnd = LPCreateDialogW(IDD_NEWABOUT1EGG,hwndDlg,about1EggProc);
  1070. }
  1071. ShowWindow(egg_wnd, SW_SHOW);
  1072. }
  1073. else
  1074. {
  1075. if ((GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_SHIFT)&0x8000))
  1076. {
  1077. if (hThread)
  1078. {
  1079. aboutThread_kill=1;
  1080. WaitForSingleObject(hThread,INFINITE);
  1081. CloseHandle(hThread);
  1082. hThread=NULL;
  1083. aboutThread_kill=0;
  1084. aboutThread_mode=!aboutThread_mode;
  1085. hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
  1086. WASABI_API_THREADPOOL->RunFunction(0, AboutThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, 0);
  1087. }
  1088. }
  1089. ShowWindow(GetDlgItem(hwndDlg,IDC_ABOUTIMG),SW_SHOW);
  1090. }
  1091. }
  1092. link_handledraw(hwndDlg,uMsg,wParam,lParam);
  1093. return 0;
  1094. }
  1095. static volatile int creditThread_kill;
  1096. static HPALETTE m_hcreditspal;
  1097. /* this thread handles the 3d credits rendering (this one does some busywork and housecleaning, actual rendering done in creditsrend.c) */
  1098. class CreditsContext
  1099. {
  1100. public:
  1101. bool Init(HWND _hwndDlg);
  1102. bool Tick(int &wait_time);
  1103. void Quit();
  1104. private:
  1105. HDC m_hdc;
  1106. HBITMAP m_hbm,m_oldhbm;
  1107. int m_pitch,m_height;
  1108. char *m_dib;
  1109. char pal[768];
  1110. struct
  1111. {
  1112. BITMAPINFO bmi;
  1113. RGBQUAD more_bmiColors[255];
  1114. } m_bitmap;
  1115. int c,use_palette;
  1116. HWND hwndDlg;
  1117. };
  1118. bool CreditsContext::Init(HWND _hwndDlg)
  1119. {
  1120. hwndDlg = _hwndDlg;
  1121. Tataki::Init(WASABI_API_SVC);
  1122. m_hcreditspal = 0;
  1123. m_hdc = 0;
  1124. m_hbm = 0;
  1125. RECT r={0,};
  1126. memset(&m_bitmap, 0, sizeof(m_bitmap));
  1127. GetWindowRect(hwndDlg,&r);
  1128. r.right=r.right-r.left;
  1129. r.bottom=r.bottom-r.top;
  1130. HDC hdc=GetWindowDC(hwndDlg);
  1131. if (!hdc)
  1132. return false;
  1133. use_palette = (GetDeviceCaps(hdc,RASTERCAPS)&RC_PALETTE)?1:0;
  1134. m_hdc = CreateCompatibleDC(NULL);
  1135. ReleaseDC(hwndDlg,hdc);
  1136. m_pitch=((r.right+3)&~3);
  1137. m_height=r.bottom;
  1138. if (m_pitch < 4) m_pitch=4;
  1139. if (m_height < 4) m_height=4;
  1140. // if (m_pitch > GetSystemMetrics(SM_CXSCREEN)) m_pitch=GetSystemMetrics(SM_CXSCREEN);
  1141. // if (m_height > GetSystemMetrics(SM_CYSCREEN)) m_height=GetSystemMetrics(SM_CYSCREEN);
  1142. render_init(m_pitch,m_height,pal);
  1143. {
  1144. struct
  1145. {
  1146. LOGPALETTE logpal;
  1147. PALETTEENTRY palentries[255];
  1148. } palette;
  1149. palette.logpal.palVersion = 0x300;
  1150. palette.logpal.palNumEntries = 220;
  1151. for (c = 0; c < 256; c ++)
  1152. {
  1153. palette.logpal.palPalEntry[c].peRed = pal[c*3];
  1154. palette.logpal.palPalEntry[c].peGreen = pal[c*3+1];
  1155. palette.logpal.palPalEntry[c].peBlue = pal[c*3+2];
  1156. palette.logpal.palPalEntry[c].peFlags = PC_NOCOLLAPSE;
  1157. m_bitmap.bmi.bmiColors[c].rgbRed=pal[c*3];
  1158. m_bitmap.bmi.bmiColors[c].rgbGreen=pal[c*3+1];
  1159. m_bitmap.bmi.bmiColors[c].rgbBlue=pal[c*3+2];
  1160. m_bitmap.bmi.bmiColors[c].rgbReserved=0;
  1161. }
  1162. if (use_palette)
  1163. m_hcreditspal = CreatePalette((LOGPALETTE *)&palette.logpal);
  1164. }
  1165. m_bitmap.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1166. m_bitmap.bmi.bmiHeader.biPlanes = 1;
  1167. m_bitmap.bmi.bmiHeader.biBitCount = 8;
  1168. m_bitmap.bmi.bmiHeader.biCompression = BI_RGB;
  1169. m_bitmap.bmi.bmiHeader.biSizeImage = 0;
  1170. m_bitmap.bmi.bmiHeader.biClrImportant = 0;
  1171. m_bitmap.bmi.bmiHeader.biClrUsed = 256;
  1172. m_bitmap.bmi.bmiHeader.biWidth = m_pitch;
  1173. m_bitmap.bmi.bmiHeader.biHeight = -m_height;
  1174. m_bitmap.bmi.bmiHeader.biSizeImage = m_pitch*m_height;
  1175. m_hbm = CreateDIBSection(m_hdc,&m_bitmap.bmi,DIB_RGB_COLORS, (void**)&m_dib, NULL, 0);
  1176. m_oldhbm = (HBITMAP) SelectObject(m_hdc, m_hbm);
  1177. return (m_hbm && m_dib);
  1178. }
  1179. void CreditsContext::Quit()
  1180. {
  1181. if (m_hbm)
  1182. {
  1183. if (m_hdc) SelectObject(m_hdc, m_oldhbm);
  1184. DeleteObject(m_hbm);
  1185. m_hbm = NULL;
  1186. m_oldhbm=NULL;
  1187. }
  1188. if (m_hcreditspal)
  1189. {
  1190. DeleteObject(m_hcreditspal);
  1191. m_hcreditspal = NULL;
  1192. }
  1193. if (m_hdc)
  1194. {
  1195. DeleteDC(m_hdc);
  1196. m_hdc=NULL;
  1197. }
  1198. render_quit();
  1199. Tataki::Quit();
  1200. }
  1201. bool CreditsContext::Tick(int &wait_time)
  1202. {
  1203. if (creditThread_kill)
  1204. return false;
  1205. unsigned int thist=GetTickCount();
  1206. render_render((unsigned char*)m_dib, m_hdc);
  1207. {
  1208. HDC h=GetDC(hwndDlg);
  1209. if (h)
  1210. {
  1211. if (m_hcreditspal)
  1212. {
  1213. SelectPalette(h,m_hcreditspal,FALSE);
  1214. RealizePalette(h);
  1215. }
  1216. BitBlt(h,0,0,m_pitch,m_height,m_hdc,0,0,SRCCOPY);
  1217. ReleaseDC(hwndDlg,h);
  1218. }
  1219. }
  1220. thist=GetTickCount()-thist;
  1221. if (thist > 28) thist=28;
  1222. wait_time = 30-thist;
  1223. return true;
  1224. }
  1225. static int CreditsTickThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id)
  1226. {
  1227. CreditsContext *context = (CreditsContext *)user_data;
  1228. TimerHandle t(handle);
  1229. int wait_time=30;
  1230. if (context->Tick(wait_time))
  1231. {
  1232. t.Wait(wait_time);
  1233. return 0;
  1234. }
  1235. else
  1236. {
  1237. context->Quit();
  1238. delete context;
  1239. HANDLE event = (HANDLE)id;
  1240. SetEvent(event);
  1241. WASABI_API_THREADPOOL->RemoveHandle(0, handle);
  1242. t.Close();
  1243. return 0;
  1244. }
  1245. }
  1246. static int CreditThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id)
  1247. {
  1248. CreditsContext *context = new CreditsContext;
  1249. if (context->Init((HWND)user_data))
  1250. {
  1251. TimerHandle t;
  1252. WASABI_API_THREADPOOL->AddHandle(0, t, CreditsTickThreadPoolFunc, context, id, api_threadpool::FLAG_LONG_EXECUTION);
  1253. t.Wait(30);
  1254. }
  1255. else
  1256. {
  1257. delete context;
  1258. HANDLE event = (HANDLE)id;
  1259. SetEvent(event);
  1260. }
  1261. return 0;
  1262. }
  1263. /* Window Proc for the 'credits' tab of the about screen */
  1264. static BOOL CALLBACK creditProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  1265. {
  1266. static int g_fullscreen=0;
  1267. static RECT rsave;
  1268. static HWND hOldParent;
  1269. static int oldstyle;
  1270. static HANDLE hThread;
  1271. if (uMsg == WM_LBUTTONDBLCLK)
  1272. {
  1273. render_togglecredits();
  1274. return 0;
  1275. }
  1276. if (uMsg == WM_KEYDOWN && g_fullscreen)
  1277. {
  1278. if (wParam == VK_ESCAPE)
  1279. {
  1280. PostMessageW(hwndDlg,WM_LBUTTONDOWN,0,0);
  1281. }
  1282. else PostMessageW(hMainWindow,uMsg,wParam,lParam);
  1283. }
  1284. if ((uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK) && g_fullscreen)
  1285. {
  1286. if (hThread)
  1287. {
  1288. creditThread_kill=1;
  1289. WaitForSingleObject(hThread,INFINITE);
  1290. CloseHandle(hThread);
  1291. hThread = 0;
  1292. if (g_fullscreen)
  1293. {
  1294. RECT r=rsave;
  1295. ScreenToClient(hOldParent,(LPPOINT)&r);
  1296. ScreenToClient(hOldParent,(LPPOINT)&r+1);
  1297. SetWindowLong(hwndDlg,GWL_STYLE,oldstyle);
  1298. SetParent(hwndDlg,hOldParent);
  1299. SetWindowPos(hwndDlg,0,r.left,r.top,r.right-r.left,r.bottom-r.top,SWP_NOZORDER);
  1300. }
  1301. }
  1302. g_fullscreen=0;
  1303. creditThread_kill=0;
  1304. hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
  1305. WASABI_API_THREADPOOL->RunFunction(0, CreditThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, api_threadpool::FLAG_LONG_EXECUTION);
  1306. }
  1307. else if (uMsg == WM_RBUTTONDBLCLK && !g_fullscreen)
  1308. {
  1309. RECT r;
  1310. if (hThread)
  1311. {
  1312. creditThread_kill=1;
  1313. WaitForSingleObject(hThread,INFINITE);
  1314. CloseHandle(hThread);
  1315. hThread = 0;
  1316. }
  1317. g_fullscreen=1;
  1318. GetWindowRect(hwndDlg,&rsave);
  1319. oldstyle=GetWindowLongW(hwndDlg,GWL_STYLE);
  1320. hOldParent=SetParent(hwndDlg,NULL);
  1321. SetWindowLong(hwndDlg,GWL_STYLE,WS_POPUP|WS_VISIBLE);
  1322. getViewport(&r,hwndDlg,1,NULL);
  1323. SetWindowPos(hwndDlg, HWND_TOPMOST, r.left, r.top, r.right, r.bottom, SWP_DRAWFRAME);
  1324. creditThread_kill=0;
  1325. hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
  1326. WASABI_API_THREADPOOL->RunFunction(0, CreditThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, api_threadpool::FLAG_LONG_EXECUTION);
  1327. // go fullscreen
  1328. }
  1329. if (uMsg == WM_INITDIALOG)
  1330. {
  1331. if (!hThread)
  1332. {
  1333. g_fullscreen=0;
  1334. creditThread_kill=0;
  1335. hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
  1336. WASABI_API_THREADPOOL->RunFunction(0, CreditThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, api_threadpool::FLAG_LONG_EXECUTION);
  1337. }
  1338. return TRUE;
  1339. }
  1340. if (uMsg == WM_QUERYNEWPALETTE)
  1341. {
  1342. if (m_hcreditspal)
  1343. {
  1344. HDC hdc = GetWindowDC(hwndDlg);
  1345. SelectPalette(hdc,m_hcreditspal,FALSE);
  1346. RealizePalette(hdc);
  1347. InvalidateRect(hwndDlg,NULL,FALSE);
  1348. ReleaseDC(hwndDlg,hdc);
  1349. return 1;
  1350. }
  1351. return 0;
  1352. }
  1353. if (uMsg == WM_PALETTECHANGED)
  1354. {
  1355. if (m_hcreditspal)
  1356. {
  1357. HDC hdc = GetWindowDC(hwndDlg);
  1358. SelectPalette(hdc,m_hcreditspal,FALSE);
  1359. RealizePalette(hdc);
  1360. UpdateColors(hdc);
  1361. ReleaseDC(hwndDlg,hdc);
  1362. return 1;
  1363. }
  1364. return 0;
  1365. }
  1366. if (uMsg == WM_DESTROY)
  1367. {
  1368. if (hThread)
  1369. {
  1370. creditThread_kill=1;
  1371. WaitForSingleObject(hThread,INFINITE);
  1372. CloseHandle(hThread);
  1373. hThread=NULL;
  1374. }
  1375. }
  1376. return 0;
  1377. }
  1378. static BOOL CALLBACK translationProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  1379. {
  1380. switch (uMsg)
  1381. {
  1382. case WM_INITDIALOG:
  1383. {
  1384. // only attempt set it to show a hand cursor if it's an ownerdraw button
  1385. if(GetWindowLongPtrW(GetDlgItem(hwndDlg, IDC_AUTHOR_HOMEPAGE), GWL_STYLE) & BS_OWNERDRAW)
  1386. {
  1387. link_startsubclass(hwndDlg, IDC_AUTHOR_HOMEPAGE);
  1388. }
  1389. if(GetWindowLongPtrW(GetDlgItem(hwndDlg, IDC_AUTHOR_HOMEPAGE2), GWL_STYLE) & BS_OWNERDRAW)
  1390. {
  1391. link_startsubclass(hwndDlg, IDC_AUTHOR_HOMEPAGE2);
  1392. }
  1393. }
  1394. break;
  1395. case WM_COMMAND:
  1396. if(LOWORD(wParam) == IDCANCEL)
  1397. {
  1398. DestroyWindow(about_hwnd);
  1399. }
  1400. else if (LOWORD(wParam) == IDC_AUTHOR_HOMEPAGE)
  1401. {
  1402. wchar_t homepage[1024] = {0};
  1403. getStringW(IDS_AUTHOR_HOMEPAGE, homepage, 1024);
  1404. myOpenURL(hwndDlg, homepage);
  1405. }
  1406. else if (LOWORD(wParam) == IDC_AUTHOR_HOMEPAGE2)
  1407. {
  1408. wchar_t homepage[1024] = {0};
  1409. getStringW(IDS_AUTHOR_HOMEPAGE2, homepage, 1024);
  1410. myOpenURL(hwndDlg, homepage);
  1411. }
  1412. break;
  1413. }
  1414. link_handledraw(hwndDlg,uMsg,wParam,lParam);
  1415. return 0;
  1416. }