Skins.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  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 "../nu/AutoWide.h"
  10. #include "../nu/AutoChar.h"
  11. #include "../nu/ns_wc.h"
  12. #include "minizip/unzip.h"
  13. #include "api.h"
  14. int g_skinloadedmanually;
  15. int g_skinmissinggenff = 0;
  16. HWND skin_hwnd;
  17. BOOL _cleanupDirW(const wchar_t *dir)
  18. {
  19. wchar_t dirmask[MAX_PATH] = {0};
  20. HANDLE h;
  21. WIN32_FIND_DATAW d = {0};
  22. PathCombineW(dirmask, dir, L"*.*");
  23. h = FindFirstFileW(dirmask, &d);
  24. if (h != INVALID_HANDLE_VALUE)
  25. {
  26. do
  27. {
  28. wchar_t v[MAX_PATH] = {0};
  29. PathCombineW(v, dir, d.cFileName);
  30. if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  31. {
  32. if (wcscmp(d.cFileName,L".") && wcscmp(d.cFileName,L".."))
  33. _cleanupDirW(v);
  34. }
  35. else
  36. {
  37. if(!DeleteFileW(v))
  38. {
  39. // this handles some rogue cases where files in the wlz's aren't unloadable
  40. MoveFileExW(v, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  41. MoveFileExW(dir, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  42. }
  43. }
  44. }
  45. while (FindNextFileW(h, &d));
  46. FindClose(h);
  47. }
  48. return RemoveDirectoryW(dir);
  49. }
  50. // attempt to cleanup the last extracted temp folder for a skin incase Winamp crashed on exit
  51. void Skin_CleanupAfterCrash(void)
  52. {
  53. wchar_t buf[1024] = {0};
  54. char str[78] = {0};
  55. StringCchPrintfA(str,78,"skin_clean_up%ws",szAppName);
  56. _r_sW(str, buf, sizeof(buf));
  57. if (buf[0])
  58. {
  59. _cleanupDirW(buf);
  60. _w_sW(str, 0);
  61. }
  62. }
  63. void Skin_CleanupZip(void)
  64. {
  65. if (!SKINTEMPDIR[0]) return ;
  66. if (_cleanupDirW(SKINTEMPDIR))
  67. {
  68. char str[78] = {0};
  69. StringCchPrintfA(str,78,"skin_clean_up%ws",szAppName);
  70. _w_s(str, 0);
  71. }
  72. }
  73. void CreateDirectoryForFileW(wchar_t *fn, wchar_t *base)
  74. {
  75. wchar_t buf1[MAX_PATH] = {0};
  76. wchar_t *tmp;
  77. wchar_t *p;
  78. StringCchCopyW(buf1, MAX_PATH, fn);
  79. tmp = scanstr_backW(buf1, L"\\/", buf1);
  80. *tmp = 0;
  81. tmp = buf1;
  82. while (tmp && *tmp) { if (*tmp == L'/') *tmp = L'\\'; tmp++; }
  83. p = buf1 + wcslen(base);
  84. while (p && *p)
  85. {
  86. while (p && *p != L'\\' && *p) p = CharNextW(p);
  87. if (p && !*p) CreateDirectoryW(buf1, NULL);
  88. else
  89. {
  90. if (p) *p = 0;
  91. CreateDirectoryW(buf1, NULL);
  92. if (p) *p++ = L'\\';
  93. }
  94. }
  95. }
  96. static void make_skin_dir(void)
  97. {
  98. if (config_skin[0])
  99. {
  100. if (_wcsicmp(extensionW(config_skin), L"zip") && _wcsicmp(extensionW(config_skin), L"wsz") && _wcsicmp(extensionW(config_skin), L"wal"))
  101. {
  102. if (PathIsFileSpecW(config_skin) || PathIsRelativeW(config_skin))
  103. PathCombineW(skin_directory, SKINDIR, config_skin);
  104. else
  105. StringCchCopyW(skin_directory, MAX_PATH, config_skin);
  106. }
  107. else
  108. {
  109. wchar_t dirmask[MAX_PATH] = {0};
  110. char str[78] = {0};
  111. StringCchCopyW(skin_directory, MAX_PATH, SKINTEMPDIR);
  112. CreateDirectoryW(SKINTEMPDIR, NULL);
  113. StringCchPrintfA(str, 78, "skin_clean_up%ws", szAppName);
  114. _w_sW(str, SKINTEMPDIR);
  115. {
  116. unzFile f;
  117. if (PathIsFileSpecW(config_skin) || PathIsRelativeW(config_skin))
  118. PathCombineW(dirmask, SKINDIR, config_skin);
  119. else
  120. StringCchCopyW(dirmask, MAX_PATH, config_skin);
  121. f = unzOpen(AutoChar(dirmask));
  122. if (f)
  123. {
  124. int iswa3 = 0;
  125. if (unzGoToFirstFile(f) == UNZ_OK)
  126. {
  127. wchar_t buriedskinxml[MAX_PATH] = {0};
  128. wchar_t *p;
  129. StringCchCopyW(buriedskinxml, MAX_PATH, config_skin);
  130. p = wcschr(buriedskinxml, '.');
  131. if (p) *p = 0;
  132. StringCchCatW(buriedskinxml, MAX_PATH, L"/skin.xml");
  133. do
  134. {
  135. char filename[MAX_PATH] = {0};
  136. unzGetCurrentFileInfo(f, NULL, filename, sizeof(filename), NULL, 0, NULL, 0);
  137. if (!_stricmp(filename, "skin.xml") || !_stricmp(filename, AutoChar(buriedskinxml))) iswa3++;
  138. }
  139. while (!iswa3 && unzGoToNextFile(f) == UNZ_OK);
  140. }
  141. if (unzGoToFirstFile(f) == UNZ_OK)
  142. {
  143. OVERLAPPED asyncIO = {0};
  144. int isNT = (GetVersion() < 0x80000000);
  145. if (isNT)
  146. {
  147. asyncIO.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
  148. asyncIO.OffsetHigh = 0;
  149. }
  150. do
  151. {
  152. char filename[MAX_PATH], *fn, *p;
  153. if (isNT)
  154. SetEvent(asyncIO.hEvent);
  155. unzGetCurrentFileInfo(f, NULL, filename, sizeof(filename), NULL, 0, NULL, 0);
  156. //Only extract the file-types that could be in a skin
  157. //If we don't filter here it's a security hole
  158. if (iswa3)
  159. {
  160. if (unzOpenCurrentFile(f) == UNZ_OK)
  161. {
  162. fn = filename;
  163. if (strstr(fn, ":")) fn = strstr(fn, ":") + 1;
  164. while (fn && *fn == '\\') fn++;
  165. p = extension(fn);
  166. // TODO: really should enum image loaders so we only extract supported image files
  167. if (fn[0] && (p != NULL && (!_stricmp(p, "xml") || !_stricmp(p, "png") ||
  168. !_stricmp(p, "cur") || !_stricmp(p, "bmp") || !_stricmp(p, "txt") ||
  169. !_stricmp(p, "gif") || !_stricmp(p, "ttf") || !_stricmp(p, "m") ||
  170. !_stricmp(p, "maki") || !_stricmp(p, "mp3") || !_stricmp(p, "wma") ||
  171. !_stricmp(p, "nsv") || !_stricmp(p, "nsa") || !_stricmp(p, "m4a") ||
  172. !_stricmp(p, "avi") || !_stricmp(p, "wav") || !_stricmp(p, "mp4") ||
  173. !_stricmp(p, "ogg") || IsPlaylistExtension(AutoWide(p)) ||
  174. !_stricmp(p, "mpg") || !_stricmp(p, "mid") || !_stricmp(p, "midi") ||
  175. !_stricmp(p, "mpeg") || !_stricmp(p, "url") || !_stricmp(p, "jpg") ||
  176. !_stricmp(p, "mi") ) ) )
  177. {
  178. PathCombineW(dirmask, SKINTEMPDIR, AutoWide(fn));
  179. CreateDirectoryForFileW(dirmask, SKINTEMPDIR);
  180. goto do_write;
  181. }
  182. }
  183. }
  184. else
  185. {
  186. fn = scanstr_back(filename, "\\/", filename - 1);
  187. p = extension(++fn);
  188. if (!_stricmp(p, "txt") || !_stricmp(p, "cur") || !_stricmp(p, "bmp") || !_stricmp(p, "ini"))
  189. {
  190. int success = 0;
  191. if (unzOpenCurrentFile(f) == UNZ_OK)
  192. {
  193. HANDLE fp;
  194. PathCombineW(dirmask, SKINTEMPDIR, AutoWide(fn));
  195. do_write:
  196. //fp = fopen(dirmask,"wb");
  197. fp = CreateFileW(dirmask, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | (isNT ? FILE_FLAG_OVERLAPPED : 0), NULL);
  198. if (fp != INVALID_HANDLE_VALUE)
  199. {
  200. int l = 0, pos = 0, bufNum=0;
  201. #define SKIN_ZIP_BUFFER_SIZE 2048
  202. char buf[SKIN_ZIP_BUFFER_SIZE*2] = {0};
  203. success = 1;
  204. do
  205. {
  206. DWORD written = 0;
  207. bufNum = !bufNum; // bufNum = (bufNUm + 1) %2;
  208. l = unzReadCurrentFile(f, buf+SKIN_ZIP_BUFFER_SIZE*bufNum, SKIN_ZIP_BUFFER_SIZE);
  209. if (!l)
  210. unzCloseCurrentFile(f);
  211. if (isNT)
  212. {
  213. WaitForSingleObject(asyncIO.hEvent, INFINITE);
  214. if (l > 0)
  215. {
  216. asyncIO.Offset = pos;
  217. if (WriteFile(fp, buf+SKIN_ZIP_BUFFER_SIZE*bufNum, l, NULL, &asyncIO) == FALSE
  218. && GetLastError() != ERROR_IO_PENDING)
  219. {
  220. success=0;
  221. }
  222. pos += l;
  223. }
  224. }
  225. else
  226. {
  227. if (l > 0)
  228. {
  229. if (WriteFile(fp, buf+SKIN_ZIP_BUFFER_SIZE*bufNum, l, &written, NULL) == FALSE)
  230. success = 0;
  231. }
  232. }
  233. } while (l > 0 && success);
  234. CloseHandle(fp);
  235. }
  236. }
  237. }
  238. }
  239. }
  240. while (unzGoToNextFile(f) == UNZ_OK);
  241. if (isNT && asyncIO.hEvent)
  242. {
  243. CloseHandle(asyncIO.hEvent);
  244. }
  245. }
  246. unzClose(f);
  247. }
  248. }
  249. }
  250. }
  251. else skin_directory[0] = 0;
  252. }
  253. int Skin_PLColors[6] =
  254. {
  255. RGB(0, 255, 0),
  256. RGB(255, 255, 255),
  257. RGB(0, 0, 0),
  258. RGB(0, 0, 198),
  259. RGB(0, 255, 0),
  260. RGB(0, 0, 0),
  261. }, Skin_UseGenNums = 0;
  262. char Skin_PLFont[128] = "";
  263. wchar_t Skin_PLFontW[128] = L"";
  264. static BOOL CALLBACK skinDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  265. static int *skin_rgn_points, *skin_rgn_numpoints, skin_rgn_numpoints_tot;
  266. static int *skin_rgn_points_eq, *skin_rgn_numpoints_eq, skin_rgn_numpoints_tot_eq;
  267. static int *skin_rgn_points_eq_ws, *skin_rgn_numpoints_eq_ws, skin_rgn_numpoints_tot_eq_ws;
  268. static int *skin_rgn_points_ws, *skin_rgn_numpoints_ws, skin_rgn_numpoints_tot_ws;
  269. static int *skin_rgn_points_pl, *skin_rgn_numpoints_pl, skin_rgn_numpoints_tot_pl;
  270. static int *skin_rgn_points_pl_ws, *skin_rgn_numpoints_pl_ws, skin_rgn_numpoints_tot_pl_ws;
  271. int Skin_GetRegionPointList( int eq, int **points, int **counts )
  272. {
  273. if ( !eq )
  274. {
  275. if ( config_windowshade )
  276. {
  277. *points = skin_rgn_points_ws;
  278. *counts = skin_rgn_numpoints_ws;
  279. return skin_rgn_numpoints_tot_ws;
  280. }
  281. else
  282. {
  283. *points = skin_rgn_points;
  284. *counts = skin_rgn_numpoints;
  285. return skin_rgn_numpoints_tot;
  286. }
  287. }
  288. else if ( eq == 1 )
  289. {
  290. if ( config_eq_ws )
  291. {
  292. *points = skin_rgn_points_eq_ws;
  293. *counts = skin_rgn_numpoints_eq_ws;
  294. return skin_rgn_numpoints_tot_eq_ws;
  295. }
  296. else
  297. {
  298. *points = skin_rgn_points_eq;
  299. *counts = skin_rgn_numpoints_eq;
  300. return skin_rgn_numpoints_tot_eq;
  301. }
  302. }
  303. else if ( eq == 2 )
  304. {
  305. if ( config_pe_height == 14 )
  306. {
  307. *points = skin_rgn_points_pl_ws;
  308. *counts = skin_rgn_numpoints_pl_ws;
  309. return skin_rgn_numpoints_tot_pl_ws;
  310. }
  311. else
  312. {
  313. *points = skin_rgn_points_pl;
  314. *counts = skin_rgn_numpoints_pl;
  315. return skin_rgn_numpoints_tot_pl;
  316. }
  317. }
  318. return 0;
  319. }
  320. static int getnums( char *section, char *name, const wchar_t *fn, int **list )
  321. {
  322. char buf[ 65535 ] = { 0 }, *p = buf;
  323. int n = 0, nn;
  324. GetPrivateProfileStringA( section, name, "", buf, sizeof( buf ), AutoChar( fn ) );
  325. while ( p )
  326. {
  327. int t = 0;
  328. while ( p && ( *p == ' ' || *p == '\t' || *p == ',' ) ) p++;
  329. if ( p && *p == '-' ) p++;
  330. while ( p && ( *p >= '0' && *p <= '9' ) )
  331. {
  332. t = 1; p++;
  333. }
  334. if ( t ) n++;
  335. else break;
  336. }
  337. if ( !n )
  338. return 0;
  339. p = buf;
  340. list[ 0 ] = (int *) GlobalAlloc( GPTR, sizeof( int ) * n );
  341. nn = n;
  342. n = 0;
  343. while ( p && n < nn )
  344. {
  345. int t = 0;
  346. int s = 0, sign = 1;
  347. while ( p && ( *p == ' ' || *p == '\t' || *p == ',' ) )
  348. p++;
  349. if ( p && *p == '-' )
  350. {
  351. sign = -1; p++;
  352. }
  353. while ( p && ( *p >= '0' && *p <= '9' ) )
  354. {
  355. s = s * 10 + *p++ - '0'; t = 1;
  356. }
  357. if ( t )
  358. list[ 0 ][ n++ ] = s * sign;
  359. else
  360. break;
  361. }
  362. return n;
  363. }
  364. static int hexGetPrivateProfileInt( char *sec, char *key, int def, const wchar_t *fn )
  365. {
  366. char str[ 100 ] = { 0 }, *s = str;
  367. if ( !GetPrivateProfileStringA( sec, key, "", str, sizeof( str ), AutoChar( fn ) ) || !*str )
  368. return def;
  369. if ( s && *s == '#' )
  370. s++;
  371. if ( s )
  372. def = strtol( s, &s, 16 );
  373. int r = ( def >> 16 ) & 255;
  374. int g = ( def >> 8 ) & 255;
  375. int b = def & 255;
  376. return RGB( r, g, b );
  377. }
  378. HCURSOR Skin_Cursors[ N_CURSORS ];
  379. static void Skin_LoadCursors( void )
  380. {
  381. static struct
  382. {
  383. int cid;
  384. const wchar_t *fn;
  385. }
  386. cursor_loads[ N_CURSORS ] =
  387. {
  388. // main, non windowshade, start 0, end 8
  389. {IDC_LRSCROLL, L"VolBal.cur"}, // vol & bal
  390. {IDC_LRSCROLL, L"Posbar.cur"}, // pos
  391. {IDC_NORMALCURSOR, L"WinBut.cur"}, //wshade
  392. {IDC_NORMALCURSOR, L"Min.cur"}, //min
  393. {IDC_DANGER, L"Close.cur"}, //close
  394. {IDC_NORMALCURSOR, L"MainMenu.cur"}, //mainmenu
  395. {IDC_MOVEMAIN, L"TitleBar.cur"}, // titelbar
  396. {IDC_LRSCROLL, L"SongName.cur"},
  397. {IDC_NORMALCURSOR, L"Normal.cur"},
  398. // main, windowshade, start 9, end 14
  399. {IDC_NORMALCURSOR, L"WinBut.cur"}, //wshade
  400. {IDC_NORMALCURSOR, L"Min.cur"}, //min
  401. {IDC_LRSCROLL, L"WSPosbar.cur"}, // seeker
  402. {IDC_DANGER, L"Close.cur"}, //close
  403. {IDC_NORMALCURSOR, L"MMenu.cur"}, //mainmenu
  404. {IDC_NORMALCURSOR, L"WSNormal.cur"},
  405. // playlist editor, normal, start 15 end 20
  406. {IDC_NORMALCURSOR, L"PWinBut.cur"}, //wshade
  407. {IDC_DANGER, L"PClose.cur"}, //close
  408. {IDC_MOVEMAIN, L"PTBar.cur"}, // titelbar
  409. {IDC_UDSCROLL, L"PVScroll.cur"},
  410. {IDC_RESIZE, L"PSize.cur"},
  411. {IDC_NORMALCURSOR, L"PNormal.cur"},
  412. // playlist editor, windowshade, start 21 end 24
  413. {IDC_NORMALCURSOR, L"PWinBut.cur"}, //wshade
  414. {IDC_DANGER, L"PClose.cur"}, //close
  415. {IDC_LRSCROLL, L"PWSSize.cur"}, //size
  416. {IDC_NORMALCURSOR, L"PWSNorm.cur"},
  417. // equalizer start 25, end 28
  418. {IDC_UDSCROLL, L"EQSlid.cur"},
  419. {IDC_DANGER, L"EQClose.cur"}, //close
  420. {IDC_MOVEMAIN, L"EQTitle.cur"}, // titelbar
  421. {IDC_NORMALCURSOR, L"EQNormal.cur"},
  422. };
  423. int x;
  424. for ( x = 0; x < N_CURSORS; x++ )
  425. {
  426. if ( Skin_Cursors[ x ] )
  427. DestroyCursor( Skin_Cursors[ x ] );
  428. Skin_Cursors[ x ] = 0;
  429. }
  430. for ( x = 0; x < N_CURSORS; x++ )
  431. {
  432. HCURSOR hc = 0;
  433. if ( config_skin[ 0 ] )
  434. {
  435. wchar_t sn[ MAX_PATH ] = { 0 };
  436. PathCombineW( sn, skin_directory, cursor_loads[ x ].fn );
  437. hc = (HCURSOR) LoadImageW( NULL, sn, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE );
  438. }
  439. if ( !hc )
  440. {
  441. hc = (HCURSOR) LoadImageW( hMainInstance, MAKEINTRESOURCEW( cursor_loads[ x ].cid ), IMAGE_CURSOR, 0, 0, 0 );
  442. }
  443. Skin_Cursors[ x ] = hc;
  444. }
  445. }
  446. #define COLOR_ERROR (0xff00ff)
  447. static ARGB32 parseColor( const char *color, int *error )
  448. {
  449. *error = 0;
  450. if ( color == NULL || *color == '\0' )
  451. {
  452. *error = 1;
  453. return COLOR_ERROR;
  454. }
  455. if ( strchr( color, ',' ) )
  456. {
  457. int r = 0, g = 0, b = 0;
  458. if ( sscanf( color, "%d,%d,%d", &r, &g, &b ) != 3 )
  459. {
  460. *error = 1;
  461. return COLOR_ERROR;
  462. }
  463. return RGB( r, g, b ); // our colors are reversed internally
  464. }
  465. if ( *color == '#' )
  466. {
  467. int r = 0, g = 0, b = 0;
  468. if ( sscanf( color, "#%02x%02x%02x", &r, &g, &b ) != 3 )
  469. {
  470. *error = 1;
  471. return COLOR_ERROR;
  472. }
  473. return RGB( r, g, b );
  474. }
  475. *error = 1;
  476. return COLOR_ERROR;
  477. }
  478. static void Skin_LoadFreeformColors( const wchar_t *fn )
  479. {
  480. WASABI_API_PALETTE->Reset();
  481. FILE *f = _wfopen( fn, L"rt" );
  482. if ( f )
  483. {
  484. char buffer[ 1024 ] = { 0 };
  485. if ( fgets( buffer, 1024, f ) )
  486. {
  487. size_t len = strlen( buffer );
  488. if ( buffer[ len - 1 ] == '\n' )
  489. buffer[ len - 1 ] = 0;
  490. if ( !strcmp( buffer, "[colors]" ) )
  491. {
  492. WASABI_API_PALETTE->StartTransaction();
  493. while ( !feof( f ) )
  494. {
  495. fgets( buffer, 1024, f );
  496. char *equal_pt = strchr( buffer, '=' );
  497. if ( equal_pt )
  498. {
  499. *equal_pt = 0;
  500. int error = 0;
  501. ARGB32 color = parseColor( equal_pt + 1, &error );
  502. if ( !error )
  503. {
  504. wchar_t utf8_expand[ 1024 ] = { 0 };
  505. MultiByteToWideCharSZ( CP_UTF8, 0, buffer, -1, utf8_expand, 1024 );
  506. WASABI_API_PALETTE->AddColor( utf8_expand, color );
  507. }
  508. }
  509. }
  510. WASABI_API_PALETTE->EndTransaction();
  511. }
  512. }
  513. fclose( f );
  514. }
  515. }
  516. BOOL Skin_Check_Modern_Support()
  517. {
  518. wchar_t fn[ MAX_PATH ] = { 0 };
  519. PathCombineW( fn, skin_directory, L"skin.xml" );
  520. if ( PathFileExistsW( fn ) && !GetModuleHandleW( L"gen_ff.dll" ) )
  521. {
  522. g_skinmissinggenff = 1;
  523. return FALSE;
  524. }
  525. g_skinmissinggenff = 0;
  526. return TRUE;
  527. }
  528. void Skin_Load(void)
  529. {
  530. Skin_CleanupZip();
  531. make_skin_dir();
  532. g_skinmissinggenff = 0;
  533. if (skin_rgn_points) GlobalFree(skin_rgn_points);
  534. if (skin_rgn_numpoints) GlobalFree(skin_rgn_numpoints);
  535. skin_rgn_numpoints = NULL;
  536. skin_rgn_points = NULL;
  537. if (skin_rgn_points_ws) GlobalFree(skin_rgn_points_ws);
  538. if (skin_rgn_numpoints_ws) GlobalFree(skin_rgn_numpoints_ws);
  539. skin_rgn_numpoints_ws = NULL;
  540. skin_rgn_points_ws = NULL;
  541. if (skin_rgn_points_eq) GlobalFree(skin_rgn_points_eq);
  542. if (skin_rgn_numpoints_eq) GlobalFree(skin_rgn_numpoints_eq);
  543. skin_rgn_numpoints_eq = NULL;
  544. skin_rgn_points_eq = NULL;
  545. if (skin_rgn_points_eq_ws) GlobalFree(skin_rgn_points_eq_ws);
  546. if (skin_rgn_numpoints_eq_ws) GlobalFree(skin_rgn_numpoints_eq_ws);
  547. skin_rgn_numpoints_eq_ws = NULL;
  548. skin_rgn_points_eq_ws = NULL;
  549. if (skin_rgn_points_pl) GlobalFree(skin_rgn_points_pl);
  550. if (skin_rgn_numpoints_pl) GlobalFree(skin_rgn_numpoints_pl);
  551. skin_rgn_numpoints_pl = NULL;
  552. skin_rgn_points_pl = NULL;
  553. if (skin_rgn_points_pl_ws) GlobalFree(skin_rgn_points_pl_ws);
  554. if (skin_rgn_numpoints_pl_ws) GlobalFree(skin_rgn_numpoints_pl_ws);
  555. skin_rgn_numpoints_pl_ws = NULL;
  556. skin_rgn_points_pl_ws = NULL;
  557. skin_rgn_numpoints_tot = 0;
  558. skin_rgn_numpoints_tot_ws = 0;
  559. skin_rgn_numpoints_tot_eq = 0;
  560. skin_rgn_numpoints_tot_eq_ws = 0;
  561. skin_rgn_numpoints_tot_pl = 0;
  562. skin_rgn_numpoints_tot_pl_ws = 0;
  563. int t_Skin_PLColors[6] =
  564. {
  565. RGB(0, 255, 0),
  566. RGB(255, 255, 255),
  567. RGB(0, 0, 0),
  568. RGB(0, 0, 198),
  569. RGB(0, 255, 0),
  570. RGB(0, 0, 0),
  571. };
  572. memcpy(Skin_PLColors, t_Skin_PLColors, sizeof(Skin_PLColors));
  573. Skin_PLFont[0] = 0;
  574. Skin_PLFontW[0] = 0;
  575. Skin_UseGenNums = !config_skin[0];
  576. // load default freeform colors
  577. if (!config_skin[0])
  578. {
  579. WASABI_API_PALETTE->Reset();
  580. WASABI_API_PALETTE->StartTransaction();
  581. WASABI_API_PALETTE->AddColor(L"wasabi.popupmenu.background.selected", RGB(0x75, 0x74, 0x8B));
  582. WASABI_API_PALETTE->AddColor(L"wasabi.popupmenu.background", RGB(0x38, 0x37, 0x57));
  583. WASABI_API_PALETTE->AddColor(L"wasabi.popupmenu.text", RGB(0xFF, 0xFF, 0xFF));
  584. WASABI_API_PALETTE->AddColor(L"wasabi.popupmenu.text.selected", RGB(0xFF, 0xFF, 0xFF));
  585. WASABI_API_PALETTE->AddColor(L"wasabi.popupmenu.text.inactive", RGB(0x73, 0x73, 0x89));
  586. WASABI_API_PALETTE->AddColor(L"wasabi.popupmenu.frame", RGB(0x75, 0x74, 0x8B));
  587. WASABI_API_PALETTE->AddColor(L"wasabi.popupmenu.separator", RGB(0x75, 0x74, 0x8B));
  588. WASABI_API_PALETTE->AddColor(L"wasabi.tooltip.background", RGB(0x38, 0x37, 0x57));
  589. WASABI_API_PALETTE->AddColor(L"wasabi.tooltip.text", RGB(0xFF, 0xFF, 0xFF));
  590. WASABI_API_PALETTE->AddColor(L"wasabi.tooltip.frame", RGB(0x75, 0x74, 0x8B));
  591. WASABI_API_PALETTE->EndTransaction();
  592. }
  593. if (skin_directory[0])
  594. {
  595. if (!Skin_Check_Modern_Support())
  596. {
  597. Skin_LoadCursors();
  598. return;
  599. }
  600. wchar_t fn[MAX_PATH] = {0};
  601. PathCombineW(fn, skin_directory, L"region.txt");
  602. skin_rgn_numpoints_tot = getnums("Normal", "NumPoints", fn, &skin_rgn_numpoints);
  603. if (skin_rgn_numpoints_tot)
  604. {
  605. int all_p;
  606. if ((all_p = getnums("Normal", "PointList", fn, &skin_rgn_points)))
  607. {
  608. int o = 0;
  609. int x;
  610. for (x = 0; x < skin_rgn_numpoints_tot; x ++)
  611. o += skin_rgn_numpoints[x];
  612. if (o == all_p / 2 && !(all_p & 1)) goto s1;
  613. // else MessageBox(NULL,"region.txt:\n[Normal]\npoints in PointList\ndon't match NumPoints","Error in skin:",0);
  614. }
  615. }
  616. if (skin_rgn_numpoints) GlobalFree(skin_rgn_numpoints);
  617. if (skin_rgn_points) GlobalFree(skin_rgn_points);
  618. skin_rgn_numpoints_tot = 0;
  619. skin_rgn_numpoints = NULL;
  620. skin_rgn_points = NULL;
  621. s1:
  622. skin_rgn_numpoints_tot_ws = getnums("WindowShade", "NumPoints", fn, &skin_rgn_numpoints_ws);
  623. if (skin_rgn_numpoints_tot_ws)
  624. {
  625. int all_p;
  626. if ((all_p = getnums("WindowShade", "PointList", fn, &skin_rgn_points_ws)))
  627. {
  628. int o = 0;
  629. int x;
  630. for (x = 0; x < skin_rgn_numpoints_tot_ws; x ++)
  631. o += skin_rgn_numpoints_ws[x];
  632. if (o == all_p / 2 && !(all_p & 1)) goto s2;
  633. // else MessageBox(NULL,"region.txt:\n[Windowshade]\npoints in PointList\ndon't match NumPoints","Error in skin:",0);
  634. }
  635. }
  636. if (skin_rgn_numpoints_ws) GlobalFree(skin_rgn_numpoints_ws);
  637. if (skin_rgn_points_ws) GlobalFree(skin_rgn_points_ws);
  638. skin_rgn_numpoints_ws = NULL;
  639. skin_rgn_numpoints_tot_ws = 0;
  640. skin_rgn_points_ws = NULL;
  641. s2:
  642. skin_rgn_numpoints_tot_eq = getnums("Equalizer", "NumPoints", fn, &skin_rgn_numpoints_eq);
  643. if (skin_rgn_numpoints_tot_eq)
  644. {
  645. int all_p;
  646. if ((all_p = getnums("Equalizer", "PointList", fn, &skin_rgn_points_eq)))
  647. {
  648. int o = 0;
  649. int x;
  650. for (x = 0; x < skin_rgn_numpoints_tot_eq; x ++)
  651. o += skin_rgn_numpoints_eq[x];
  652. if (o == all_p / 2 && !(all_p & 1)) goto s3;
  653. // else MessageBox(NULL,"region.txt:\n[Equalizer]\npoints in PointList\ndon't match NumPoints","Error in skin:",0);
  654. }
  655. }
  656. if (skin_rgn_numpoints_eq) GlobalFree(skin_rgn_numpoints_eq);
  657. if (skin_rgn_points_eq) GlobalFree(skin_rgn_points_eq);
  658. skin_rgn_numpoints_eq = NULL;
  659. skin_rgn_numpoints_tot_eq = 0;
  660. skin_rgn_points_eq = NULL;
  661. s3:
  662. skin_rgn_numpoints_tot_eq_ws = getnums("EqualizerWS", "NumPoints", fn, &skin_rgn_numpoints_eq_ws);
  663. if (skin_rgn_numpoints_tot_eq_ws)
  664. {
  665. int all_p;
  666. if ((all_p = getnums("EqualizerWS", "PointList", fn, &skin_rgn_points_eq_ws)))
  667. {
  668. int o = 0;
  669. int x;
  670. for (x = 0; x < skin_rgn_numpoints_tot_eq_ws; x ++)
  671. o += skin_rgn_numpoints_eq_ws[x];
  672. if (o == all_p / 2 && !(all_p & 1)) goto s4;
  673. // else MessageBox(NULL,"region.txt:\n[EqualizerWS]\npoints in PointList\ndon't match NumPoints","Error in skin:",0);
  674. }
  675. }
  676. if (skin_rgn_numpoints_eq_ws) GlobalFree(skin_rgn_numpoints_eq_ws);
  677. if (skin_rgn_points_eq_ws) GlobalFree(skin_rgn_points_eq_ws);
  678. skin_rgn_numpoints_eq_ws = NULL;
  679. skin_rgn_numpoints_tot_eq_ws = 0;
  680. skin_rgn_points_eq_ws = NULL;
  681. s4:
  682. /*skin_rgn_numpoints_tot_pl = getnums("Playlist", "NumPoints", fn, &skin_rgn_numpoints_pl);
  683. if (skin_rgn_numpoints_tot_pl)
  684. {
  685. int all_p;
  686. if ((all_p = getnums("Playlist", "PointList", fn, &skin_rgn_points_pl)))
  687. {
  688. int o = 0;
  689. int x;
  690. for (x = 0; x < skin_rgn_numpoints_tot_pl; x ++)
  691. o += skin_rgn_numpoints_pl[x];
  692. if (o == all_p / 2 && !(all_p & 1)) goto s5;
  693. // else MessageBox(NULL,"region.txt:\n[Playlist]\npoints in PointList\ndon't match NumPoints","Error in skin:",0);
  694. }
  695. }*/
  696. if (skin_rgn_numpoints_pl) GlobalFree(skin_rgn_numpoints_pl);
  697. if (skin_rgn_points_pl) GlobalFree(skin_rgn_points_pl);
  698. skin_rgn_numpoints_pl = NULL;
  699. skin_rgn_numpoints_tot_pl = 0;
  700. skin_rgn_points_pl = NULL;
  701. //s5:
  702. /*skin_rgn_numpoints_tot_pl_ws = getnums("PlaylistWS", "NumPoints", fn, &skin_rgn_numpoints_pl_ws);
  703. if (skin_rgn_numpoints_tot_pl_ws)
  704. {
  705. int all_p;
  706. if ((all_p = getnums("PlaylistWS", "PointList", fn, &skin_rgn_points_pl_ws)))
  707. {
  708. int o = 0;
  709. int x;
  710. for (x = 0; x < skin_rgn_numpoints_tot_pl_ws; x ++)
  711. o += skin_rgn_numpoints_pl_ws[x];
  712. if (o == all_p / 2 && !(all_p & 1)) goto s6;
  713. // else MessageBox(NULL,"region.txt:\n[PlaylistWS]\npoints in PointList\ndon't match NumPoints","Error in skin:",0);
  714. }
  715. }*/
  716. // if (skin_rgn_numpoints_pl_ws) GlobalFree(skin_rgn_numpoints_pl_ws);
  717. // if (skin_rgn_points_pl_ws) GlobalFree(skin_rgn_points_pl_ws);
  718. // skin_rgn_numpoints_pl_ws = NULL;
  719. // skin_rgn_numpoints_tot_pl_ws = 0;
  720. // skin_rgn_points_pl_ws = NULL;
  721. //s6:
  722. // ;
  723. #if 0
  724. {
  725. char str[1024] = {0};
  726. PathCombine(fn, skin_directory, "mb.ini");
  727. GetPrivateProfileString("Winamp", "MBOpen", "", str, sizeof(str), fn);
  728. str[1023] = 0;
  729. if (str[0])
  730. {
  731. if (hMBWindow)
  732. {
  733. if (g_skinloadedmanually) SendMessageW(hMainWindow, WM_USER, (WPARAM)0, IPC_MBOPEN);
  734. SendMessageW(hMainWindow, WM_USER, (WPARAM)str, IPC_MBOPEN);
  735. }
  736. else
  737. {
  738. extern char page_nav[1024];
  739. if (g_skinloadedmanually) config_mb_open = 1;
  740. lstrcpy(page_nav, str);
  741. }
  742. }
  743. }
  744. #endif
  745. PathCombineW(fn, skin_directory, L"pledit.txt");
  746. Skin_PLColors[0] = hexGetPrivateProfileInt("Text", "Normal", Skin_PLColors[0], fn);
  747. Skin_PLColors[1] = hexGetPrivateProfileInt("Text", "Current", Skin_PLColors[1], fn);
  748. Skin_PLColors[2] = hexGetPrivateProfileInt("Text", "NormalBG", Skin_PLColors[2], fn);
  749. Skin_PLColors[3] = hexGetPrivateProfileInt("Text", "SelectedBG", Skin_PLColors[3], fn);
  750. Skin_PLColors[4] = hexGetPrivateProfileInt("Text", "mbFG", Skin_PLColors[4], fn);
  751. Skin_PLColors[5] = hexGetPrivateProfileInt("Text", "mbBG", Skin_PLColors[5], fn);
  752. char plfont[256] = {0};
  753. GetPrivateProfileStringA("Text", "Font", "", plfont, 256, AutoChar(fn));
  754. MultiByteToWideCharSZ(CP_UTF8, 0, plfont, -1, Skin_PLFontW, sizeof(Skin_PLFontW)/sizeof(*Skin_PLFontW));
  755. WideCharToMultiByteSZ(CP_ACP, 0, Skin_PLFontW, -1, Skin_PLFont, sizeof(Skin_PLFont)/sizeof(*Skin_PLFont), 0, 0);
  756. // used to allow for the gen.bmp numbers support in 5.64 - need skin to say as too many have junk where it's taken from
  757. Skin_UseGenNums = GetPrivateProfileIntW(L"Misc", L"UseGenNums", 0, fn);
  758. PathCombineW(fn, skin_directory, L"colors.ini");
  759. Skin_LoadFreeformColors(fn);
  760. }
  761. Skin_LoadCursors();
  762. }
  763. void Skin_Random(void)
  764. {
  765. if (config_randskin)
  766. {
  767. HANDLE h;
  768. WIN32_FIND_DATAW d = {0};
  769. int v, x;
  770. wchar_t dirmask[MAX_PATH] = {0};
  771. PathCombineW(dirmask, SKINDIR, L"*");
  772. x = 1;
  773. h = FindFirstFileW(dirmask, &d);
  774. if (h != INVALID_HANDLE_VALUE)
  775. {
  776. do
  777. {
  778. if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  779. {
  780. if (wcscmp(d.cFileName, L".") && wcscmp(d.cFileName, L"..")) x++;
  781. }
  782. else if (!_wcsicmp(extensionW(d.cFileName), L"zip") || !_wcsicmp(extensionW(d.cFileName), L"wsz") || !_wcsicmp(extensionW(d.cFileName), L"wal"))
  783. x++;
  784. }
  785. while (FindNextFileW(h, &d));
  786. FindClose(h);
  787. }
  788. v = warand() % x;
  789. if (!v)
  790. {
  791. config_skin[0] = 0;
  792. return ;
  793. }
  794. x = 1;
  795. h = FindFirstFileW(dirmask, &d);
  796. if (h != INVALID_HANDLE_VALUE)
  797. {
  798. do
  799. {
  800. int t = 0;
  801. if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  802. {
  803. if (wcscmp(d.cFileName, L".") && wcscmp(d.cFileName, L"..")) t = 1;
  804. }
  805. else if (!_wcsicmp(extensionW(d.cFileName), L"zip") || !_wcsicmp(extensionW(d.cFileName), L"wsz") || !_wcsicmp(extensionW(d.cFileName), L"wal")) t = 1;
  806. if (t)
  807. {
  808. if (x == v)
  809. {
  810. StringCchCopyW(config_skin, MAX_PATH, d.cFileName);
  811. break;
  812. }
  813. x++;
  814. }
  815. }
  816. while (FindNextFileW(h, &d));
  817. FindClose(h);
  818. }
  819. PostMessageW(hMainWindow, WM_COMMAND, WINAMP_REFRESHSKIN, 0);
  820. if (prefs_last_page == 40 && IsWindow(prefs_hwnd))
  821. {
  822. prefs_last_page = 0;
  823. prefs_dialog(1);
  824. prefs_last_page = 40;
  825. prefs_dialog(1);
  826. }
  827. }
  828. }