diff options
author | Jean-Francois Mauguit <jfmauguit@mac.com> | 2024-09-24 09:03:25 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-24 09:03:25 -0400 |
commit | bab614c421ed7ae329d26bf028c4a3b1d2450f5a (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/ABOUT.cpp | |
parent | 4bde6044fddf053f31795b9eaccdd2a5a527d21f (diff) | |
parent | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (diff) | |
download | winamp-bab614c421ed7ae329d26bf028c4a3b1d2450f5a.tar.gz |
Merge pull request #5 from WinampDesktop/community
Merge to main
Diffstat (limited to 'Src/Winamp/ABOUT.cpp')
-rw-r--r-- | Src/Winamp/ABOUT.cpp | 1531 |
1 files changed, 1531 insertions, 0 deletions
diff --git a/Src/Winamp/ABOUT.cpp b/Src/Winamp/ABOUT.cpp new file mode 100644 index 00000000..9916fafc --- /dev/null +++ b/Src/Winamp/ABOUT.cpp @@ -0,0 +1,1531 @@ +/** (c) Nullsoft, Inc. C O N F I D E N T I A L +** Filename: +** Project: +** Description: +** Author: +** Created: +**/ + +#include "Main.h" +#include "language.h" +#include <math.h> +#include "../nu/threadname.h" +#include "resource.h" +#include <tataki/export.h> +#include "api.h" +#include "../nu/threadpool/TimerHandle.hpp" +#include "../nu/AutoWide.h" + +int img_w[2] = {400, 100}, img_h[2] = {189, 34}; +int about_lastpage; +HWND about_hwnd; +#define M_PI 3.14159265358979323846 + +static BOOL CALLBACK tipsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam); +static BOOL CALLBACK whatsnewProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam); +static BOOL CALLBACK about1Proc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam); +static BOOL CALLBACK creditProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam); +static BOOL CALLBACK translationProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam); +static LRESULT WINAPI aboutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam); + +static unsigned const char sq_table[]= +{0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57, 59, 61, 64, 65, +67, 69, 71, 73, 75, 76, 78, 80, 81, 83, 84, 86, 87, 89, 90, 91, 93, 94, +96, 97, 98, 99, 101, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113, +114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 128, +128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, +142, 143, 144, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, +154, 155, 155, 156, 157, 158, 159, 160, 160, 161, 162, 163, 163, 164, +165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, +176, 176, 177, 178, 178, 179, 180, 181, 181, 182, 183, 183, 184, 185, +185, 186, 187, 187, 188, 189, 189, 190, 191, 192, 192, 193, 193, 194, +195, 195, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 203, 203, +204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, 212, +212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, +221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 227, 228, +229, 229, 230, 230, 231, 231, 232, 232, 233, 234, 234, 235, 235, 236, +236, 237, 237, 238, 238, 239, 240, 240, 241, 241, 242, 242, 243, 243, +244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, +251, 251, 252, 252, 253, 253, 254, 254, 255}; + +static __inline unsigned long isqrt(unsigned long n) +{ + if (n >= 0x10000) + if (n >= 0x1000000) + if (n >= 0x10000000) + if (n >= 0x40000000) return(sq_table[n >> 24] << 8); + else return(sq_table[n >> 22] << 7); + else + if (n >= 0x4000000) return(sq_table[n >> 20] << 6); + else return(sq_table[n >> 18] << 5); + else + if (n >= 0x100000) + if (n >= 0x400000) return(sq_table[n >> 16] << 4); + else return(sq_table[n >> 14] << 3); + else + if (n >= 0x40000) return(sq_table[n >> 12] << 2); + else return(sq_table[n >> 10] << 1); + else + if (n >= 0x100) + if (n >= 0x1000) + if (n >= 0x4000) return(sq_table[n >> 8]); + else return(sq_table[n >> 6] >> 1); + else + if (n >= 0x400) return(sq_table[n >> 4] >> 2); + else return(sq_table[n >> 2] >> 3); + else + if (n >= 0x10) + if (n >= 0x40) return(sq_table[n] >> 4); + else return(sq_table[n << 2] << 5); + else + if (n >= 0x4) return(sq_table[n >> 4] << 6); + else return(sq_table[n >> 6] << 7); +} + +void about_dialog(void) +{ + if (about_hwnd) + { + SetForegroundWindow(about_hwnd); + return; + } + + about_hwnd=(HWND)LPCreateDialogW(IDD_NEWABOUT, hMainWindow, aboutProc); + + // show about window and restore last position as applicable + POINT pt = {about_rect.left, about_rect.top}; + if (!windowOffScreen(about_hwnd, pt)) + SetWindowPos(about_hwnd, HWND_TOP, about_rect.left, about_rect.top, 0, 0, SWP_NOSIZE | SWP_NOSENDCHANGING | SWP_SHOWWINDOW); + else + ShowWindow(about_hwnd, SW_SHOW); +} + +static LRESULT WINAPI aboutProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) +{ + static HWND cur_wnd; + switch (uMsg) + { + case WM_INITDIALOG: + { + int t=about_lastpage; + about_lastpage=-1; + // make sure not to show the localised page if not under a language pack + if (t==4 && config_langpack[0]) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON2, 0); + else if (t==3) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON6, 0); + else if (t==2) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON5, 0); + else if (t==1) SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON4, 0); + else + { + if (t==4) t = 0; + SendMessageW(hwndDlg, WM_COMMAND, IDC_BUTTON3, 0); + } + } + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDCANCEL: + case IDOK: + DestroyWindow(hwndDlg); + return FALSE; + case IDC_BUTTON3: + case IDC_BUTTON4: + case IDC_BUTTON5: + case IDC_BUTTON6: + case IDC_BUTTON2: + { + int id=-1; + int t = 0; + void *proc = 0; + if (LOWORD(wParam)==IDC_BUTTON3) t=0; + if (LOWORD(wParam)==IDC_BUTTON4) t=1; + if (LOWORD(wParam)==IDC_BUTTON5) t=2; + if (LOWORD(wParam)==IDC_BUTTON6) t=3; + if (LOWORD(wParam)==IDC_BUTTON2) t=4; + if (t == about_lastpage) return 0; + about_lastpage=t; + switch (t) + { + case 0: id=IDD_NEWABOUT1; proc=about1Proc; break; + case 1: id=IDD_NEWABOUT2; proc=creditProc; break; + case 2: id=IDD_NEWABOUT3; proc=tipsProc; break; + case 3: id=IDD_NEWABOUT4; proc=whatsnewProc; break; + case 4: id=IDD_ABOUT_TRANSLATION; proc=translationProc; break; + } + + if (IsWindow(cur_wnd)) + { + DestroyWindow(cur_wnd); + cur_wnd=0; + } + + if (id != -1) + { + cur_wnd = CreateDialogW(language_pack_instance, MAKEINTRESOURCEW(id), hwndDlg, (DLGPROC)proc); + // handles cases where there's no localised info page in a language pack / under en-us + if(!IsWindow(cur_wnd)) cur_wnd = LPCreateDialogW(id, hwndDlg, (DLGPROC)proc); + + { + RECT r; + GetWindowRect(GetDlgItem(hwndDlg,IDC_RECT),&r); + ScreenToClient(hwndDlg,(LPPOINT)&r); + SetWindowPos(cur_wnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER); + } + ShowWindow(cur_wnd,SW_SHOWNA); + { + RECT r,r2; + GetWindowRect(GetDlgItem(hwndDlg,IDC_BUTTON3),&r); + GetWindowRect(GetDlgItem(hwndDlg,IDC_BUTTON6),&r2); + r.right=r2.right; + ScreenToClient(hwndDlg,(LPPOINT)&r); + ScreenToClient(hwndDlg,((LPPOINT)&r)+1); + InvalidateRect(hwndDlg,&r,FALSE); + } + } + } + return FALSE; + } + break; + + case WM_DESTROY: + GetWindowRect(hwndDlg, &about_rect); + if (IsWindow(cur_wnd)) DestroyWindow(cur_wnd); + cur_wnd=0; + about_hwnd=NULL; + break; + } + + if (uMsg == WM_DRAWITEM) + { + DRAWITEMSTRUCT *di = (DRAWITEMSTRUCT *)lParam; + if (di->CtlType == ODT_BUTTON) + { + wchar_t wt[123] = {0}; + int sel=0; + RECT r; + GetDlgItemTextW(hwndDlg,wParam,wt,123); + + if (di->CtlID==IDC_BUTTON3 && about_lastpage==0) sel=1; + else if (di->CtlID==IDC_BUTTON4 && about_lastpage==1) sel=1; + else if (di->CtlID==IDC_BUTTON5 && about_lastpage==2) sel=1; + else if (di->CtlID==IDC_BUTTON6 && about_lastpage==3) sel=1; + else if (di->CtlID==IDC_BUTTON2 && about_lastpage==4) sel=1; + + if (di->CtlID != IDC_BUTTON6) + { + MoveToEx(di->hDC,di->rcItem.right-1,di->rcItem.top,NULL); + LineTo(di->hDC,di->rcItem.right-1,di->rcItem.bottom); + } + + // draw text + if (!sel && (di->itemState & (ODS_SELECTED))) + SetTextColor(di->hDC,RGB(0,40,255)); + r=di->rcItem; + DrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER); + if (sel) + { + r=di->rcItem; + r.left+=2; + SetBkMode(di->hDC,TRANSPARENT); + DrawTextW(di->hDC,wt,-1,&r,DT_VCENTER|DT_SINGLELINE|DT_CENTER); + } + } + } + return 0; +} + +/* Window Proc for the 'keyboard shorcuts' tab of about screen */ +static BOOL CALLBACK tipsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) +{ + static HGLOBAL hResource=0; + static DWORD hResourceSize=0; + switch (uMsg) + { + case WM_INITDIALOG: + { + char *b = NULL, *p = 0, *op = 0; + DWORD size = 0; + if (!hResource) + { + hResource = langManager->LoadResourceFromFileW(language_pack_instance, hMainInstance,TEXT("TEXT"), TEXT("TIPSTEXT"),&size); + hResourceSize = size; + } + p = (char*)hResource; + if (p && (op = strstr(p, "!!End"))) // if there's "!!End" in the resource, than copy everything before it + { + b = (char*)GlobalAlloc(GPTR, op-p+1); + memcpy(b, p, op-p); + b[op-p] = 0; + } else { + b = (char*)GlobalAlloc(GPTR, hResourceSize+1); + memcpy(b, p, hResourceSize); + b[hResourceSize] = 0; + } + + SetDlgItemTextA(hwndDlg, IDC_TIPS, (b ? b : p)); // send it to the text control to display + if (b) GlobalFree(b); + } + break; + + case WM_COMMAND: + if(LOWORD(wParam) == IDCANCEL) + { + DestroyWindow(about_hwnd); + } + break; + } + + if (FALSE != IsDirectMouseWheelMessage(uMsg)) + { + HWND textWindow; + RECT windowRect; + textWindow = GetDlgItem(hwndDlg, IDC_TIPS); + if (NULL != textWindow && + FALSE != GetClientRect(textWindow, &windowRect)) + { + POINT pt; + POINTSTOPOINT(pt, lParam); + + MapWindowPoints(HWND_DESKTOP, textWindow, &pt, 1); + if (FALSE != PtInRect(&windowRect, pt)) + { + SendMessageW(textWindow, WM_MOUSEWHEEL, wParam, lParam); + SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE); + } + return TRUE; + } + } + return 0; +} + +WNDPROC whatedproc = 0; +static LRESULT CALLBACK whatseditproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if(uMsg == WM_KEYDOWN) + { + if(wParam == 'F' && (GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_SHIFT)&0x8000)) + { + if(IsWindowEnabled(GetDlgItem(GetParent(hwndDlg), IDC_ABOUT_SEARCH))) + { + SendMessageW(GetParent(hwndDlg), WM_COMMAND, MAKEWPARAM(IDC_ABOUT_SEARCH,0), 0); + } + } + } + return CallWindowProcW(whatedproc,hwndDlg,uMsg,wParam,lParam); +} + +#define WHATSNEW_BUFFER_SIZE 262144 +static wchar_t* ver_buf; + +void GetWhatsNewFromFile(FILE *fp) +{ + bool utf8=false, utf16=false; + unsigned char BOM[3] = {0, 0, 0}; + if (fread(BOM, 3, 1, fp) == 1 && BOM[0] == 0xEF && BOM[1] == 0xBB && BOM[2] == 0xBF) + utf8 = true; + else + { + fseek(fp, 0, SEEK_SET); + if (fread(BOM, 2, 1, fp) == 1 && BOM[0] == 0xFF && BOM[1] == 0xFE) + utf16=true; + else + fseek(fp, 0, SEEK_SET); + } + + if (utf16) + { + wchar_t buffer[WHATSNEW_BUFFER_SIZE]={0}, *p=buffer; + for (;;) + { + fgetws(p,1024,fp); + if (feof(fp)) break; + if (p[wcslen(p)-1]==L'\n') + p[wcslen(p)-1]=0; + StringCchCatW(p,WHATSNEW_BUFFER_SIZE,L"\r\n"); + p=p+wcslen(p); + if (p-buffer > WHATSNEW_BUFFER_SIZE) break; + } + + ver_buf = wcsdup(buffer); + } + else + { + char buffer[WHATSNEW_BUFFER_SIZE]={0},*p=buffer; + for (;;) + { + fgets(p,1024,fp); + if (feof(fp)) break; + if (p[lstrlenA(p)-1]=='\n') + p[lstrlenA(p)-1]=0; + StringCchCatA(p,WHATSNEW_BUFFER_SIZE,"\r\n"); + p=p+lstrlenA(p); + if (p-buffer > WHATSNEW_BUFFER_SIZE) break; + } + + if (utf8) + { + ver_buf = AutoWideDup(buffer, CP_UTF8); + } + else + { + ver_buf = AutoWideDup(buffer); + } + } +} + +static std::map<int,wchar_t*> versions; +/* Window Proc for the 'version history' tab of about screen */ +static BOOL CALLBACK whatsnewProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static UINT fm_msg; + static FINDREPLACEW find; + static wchar_t fromstring[256]; + static HWND finder; + + if(uMsg == fm_msg) + { + LPFINDREPLACEW lpFindReplace = (LPFINDREPLACEW) lParam; + if(lpFindReplace->Flags & FR_FINDNEXT) + { + int len = GetWindowTextLengthW(GetDlgItem(hwndDlg,IDC_TIPS))+1, + flen = lstrlenW(lpFindReplace->lpstrFindWhat), start = 0, end = 0; + wchar_t *buffer = (wchar_t*)calloc((len+1),sizeof(wchar_t)), + *search = (wchar_t*)calloc((flen+2),sizeof(wchar_t)), + *result = 0; + + lstrcpynW(search,lpFindReplace->lpstrFindWhat,flen+1); + SendDlgItemMessageW(hwndDlg,IDC_TIPS,EM_GETSEL,(WPARAM)&start,(LPARAM)&end); + + GetDlgItemTextW(hwndDlg,IDC_TIPS,buffer,len); + + // handles the match case option + if(!(lpFindReplace->Flags & FR_MATCHCASE)) + { + CharUpperBuffW(buffer, len); + CharUpperBuffW(search, flen+1); + } + + if((result = wcsstr(buffer+end,search))) + { + SendDlgItemMessage(hwndDlg,IDC_TIPS,EM_SETSEL,result-buffer,(result-buffer)+flen); + SendDlgItemMessage(hwndDlg,IDC_TIPS,EM_SCROLLCARET,0,0); + } + else + { + MessageBoxW(finder,getStringW(IDS_NO_MATCHES_FOUND,NULL,0),L"Winamp",MB_ICONINFORMATION); + } + + free(buffer); + free(search); + } + } + + switch (uMsg) { + case WM_INITDIALOG: + { + wchar_t fn[MAX_PATH] = {0}; + FILE *fp = NULL; + int last_add = 0; + + whatedproc = (WNDPROC)SetWindowLongPtrW(GetDlgItem(hwndDlg,IDC_TIPS),GWLP_WNDPROC,(LONG_PTR)whatseditproc); + + SendDlgItemMessage(hwndDlg, IDC_TIPS, EM_SETLIMITTEXT, 0, 0); + + // attempt to pull a localised whatsnew.txt + // before reverting to the english default + if (lang_directory[0]) + { + lstrcpynW(fn,lang_directory,MAX_PATH); + } + else + { + GetModuleFileNameW(NULL,fn,MAX_PATH); + PathRemoveFileSpecW(fn); + } + PathAppendW(fn, L"whatsnew.txt"); + + // we don't set the buffer position so that it all works on the fallback code + // and make sure there's a selection no matter what happens with other things + SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_ADDSTRING,0,(LPARAM)getStringW(IDS_SHOW_ALL_HISTORY,NULL,0)); + SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_SETCURSEL,0,0); + + versions.clear(); + fp = _wfopen(fn,L"rb"); + + // if there isn't a localised whatsnew.txt then revert to the old ways + if(!fp) + { + GetModuleFileNameW(NULL,fn,MAX_PATH); + PathRemoveFileSpecW(fn); + PathAppendW(fn,L"whatsnew.txt"); + fp = _wfopen(fn,L"rb"); + } + + if (fp) + { + GetWhatsNewFromFile(fp); + fclose(fp); + wchar_t* p = ver_buf; + while(p && *p) + { + // populate the version combobox + if(!wcsncmp(p,L"Winamp 5.",9)) + { + wchar_t* pp = p, ver[64] = {0}; + while(pp && *pp && *pp != L'\r') pp = CharNextW(pp); + // need to make sure that we've actually found a valid part otherwise + // just skip over things and don't fill in the combobox (attempted exploit) + if(pp && *pp && *pp == L'\r'){ + pp = CharNextW(pp); + // make sure that we keep within the buffer size as some people have + // tried to make a buffer overflow vulnerability with this on XP SP3 + lstrcpynW(ver,p,(pp-p<64?pp-p:64)); + wchar_t* v = ver, *vn = 0, *vne = 0; + while(v && *v && *v != L'\t') v = CharNextW(v); + if(v && *v == L'\t'){ + vn = vne = CharNextW(v); + *v = 0; + if(vn && *vn == L'[') vn = CharNextW(vn); + while(vne && *vne && *vne != L']') vne = CharNextW(vne); + if(vne && *vne == L']') *vne = 0; + } + last_add = SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_ADDSTRING,0,(LPARAM)ver); + SendDlgItemMessageW(hwndDlg,IDC_VER_COMBO,CB_SETITEMDATA,last_add,(LPARAM)p); + versions[last_add] = wcsdup(vn); + } + } + p = CharNextW(p); + } + + // reset the selection to the last view and force an update to that + // would be better to do it straight away on load but this ensures all synchs up + SendDlgItemMessage(hwndDlg,IDC_VER_COMBO,CB_SETCURSEL,_r_i("whtsnewlp",1),0); + SendMessageW(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_VER_COMBO,CBN_SELCHANGE),(LPARAM)GetDlgItem(hwndDlg,IDC_VER_COMBO)); + } + else + { + EnableWindow(GetDlgItem(hwndDlg,IDC_VER_COMBO),0); + EnableWindow(GetDlgItem(hwndDlg,IDC_ABOUT_SEARCH),0); + SetDlgItemTextW(hwndDlg,IDC_TIPS,getStringW(IDS_WHATSNEW_FAIL,ver_buf,WHATSNEW_BUFFER_SIZE)); + } + } + return FALSE; + + case WM_COMMAND: + if(LOWORD(wParam) == IDC_VER_COMBO && HIWORD(wParam) == CBN_SELCHANGE) + { + int cur = SendMessageW((HWND)lParam,CB_GETCURSEL,0,0); + wchar_t* position = (wchar_t*)SendMessageW((HWND)lParam,CB_GETITEMDATA,cur,0); + if(cur != CB_ERR && position){ + wchar_t* p = position, *out_buf = (wchar_t*)calloc(WHATSNEW_BUFFER_SIZE,sizeof(wchar_t)), *out = out_buf; + while(p && *p) + { + if(*p == L'\t') + { + if(*CharNextW(p) == L'[') + { + wchar_t* pb = p; + while(pb && *pb && *pb != L']') + { + pb = CharNextW(pb); + } + if(pb && *pb == L']') p = CharNextW(pb); + } + } + + // look for 2 empty lines to indicate end of version block + if(*p == L'\r') + { + wchar_t* n = CharNextW(p); + if(n && *n == L'\n') + { + n = CharNextW(n); + if(n && *n == L'\r') + { + break; + } + } + } + *out = *p; + p = CharNextW(p); + out = CharNextW(out); + } + *out = 0; + + wchar_t released[128] = {0}; + if(cur == 1 || cur > 1 && versions[cur] != 0) + StringCchPrintfW(released,128,getStringW(IDS_RELEASED,NULL,0), (cur == 1 ? AutoWide(__DATE__) : versions[cur])); + else + released[0] = 0; + SendMessageW(GetDlgItem(hwndDlg,IDC_RELEASED),WM_SETTEXT,0,(LPARAM)released); + SendMessageW(GetDlgItem(hwndDlg,IDC_TIPS),WM_SETTEXT,0,(LPARAM)out_buf); + free(out_buf); + } + else{ + SendMessageW(GetDlgItem(hwndDlg,IDC_RELEASED),WM_SETTEXT,0,(LPARAM)L""); + SendMessageW(GetDlgItem(hwndDlg,IDC_TIPS),WM_SETTEXT,0,(LPARAM)ver_buf); + } + } + else if(LOWORD(wParam) == IDC_ABOUT_SEARCH) + { + if(!IsWindow(finder)) + { + if(!fm_msg) fm_msg = RegisterWindowMessageW(FINDMSGSTRINGW); + + find.lStructSize = sizeof(find); + find.hwndOwner = hwndDlg; + find.Flags = FR_DOWN|FR_HIDEWHOLEWORD|FR_HIDEUPDOWN; + find.lpstrFindWhat = fromstring; + find.wFindWhatLen = ARRAYSIZE(fromstring); + finder = FindTextW(&find); + ShowWindow(finder,SW_SHOW); + } + else + { + SetActiveWindow(finder); + } + } + + else if(LOWORD(wParam) == IDCANCEL) + { + DestroyWindow(about_hwnd); + } + break; + + case WM_DESTROY: + free(ver_buf); + ver_buf = 0; + + //for (int i=0; i!=versions.size(); i++) + // free(versions[i]); + for (auto& version : versions) + { + if (version.second) + { + free(version.second); + } + } + + versions.clear(); + _w_i("whtsnewlp",SendDlgItemMessage(hwndDlg,IDC_VER_COMBO,CB_GETCURSEL,0,0)); + if(IsWindow(finder)) DestroyWindow(finder); + break; + } + + if (FALSE != IsDirectMouseWheelMessage(uMsg)) + { + HWND textWindow; + RECT windowRect; + textWindow = GetDlgItem(hwndDlg, IDC_TIPS); + if (NULL != textWindow && + FALSE != GetClientRect(textWindow, &windowRect)) + { + POINT pt; + POINTSTOPOINT(pt, lParam); + + MapWindowPoints(HWND_DESKTOP, textWindow, &pt, 1); + if (FALSE != PtInRect(&windowRect, pt)) + { + SendMessageW(textWindow, WM_MOUSEWHEEL, wParam, lParam); + SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, TRUE); + } + return TRUE; + } + } + return 0; +} + +static volatile int aboutThread_kill, aboutThread_mode; +static HPALETTE m_haboutpal; + +/* This does the 'zooming' effect on the image in the 'winamp' tab of the about screen */ +class AboutContext +{ +public: + bool Init(HWND _hwndDlg); + bool Tick(); + void Quit(); + +private: + int mode; + static int m_wt,m_wait; + static int a; + HDC m_hdc; + HBITMAP m_hbm,m_oldhbm; + + int m_pitch,m_height; + char *m_source,*m_dib; + int m_wmul[200]; + RECT r; + HBITMAP m_imgbm, m_imgoldbm; + HDC m_imgdc; + + struct + { + BITMAPINFO bmi; + RGBQUAD more_bmiColors[256]; + LPVOID data; + } m_bitmap; + int c,use_palette; + HWND hwndDlg; +}; + +int AboutContext::m_wt = 0; +int AboutContext::m_wait = 0; +int AboutContext::a = 0; +bool AboutContext::Init(HWND _hwndDlg) +{ + hwndDlg = _hwndDlg; + mode=(GetAsyncKeyState(VK_SHIFT)&0x8000); + GetClientRect(GetDlgItem(hwndDlg,IDC_ABOUTIMG),&r); + HDC hdc=GetWindowDC(hwndDlg); + if (!hdc) + return false; + use_palette = (GetDeviceCaps(hdc,RASTERCAPS)&RC_PALETTE)?1:0; + m_hdc = CreateCompatibleDC(NULL); + m_imgdc = CreateCompatibleDC(NULL); + ReleaseDC(hwndDlg,hdc); + + if (!m_imgdc) + return false; + + m_imgbm= (HBITMAP)LoadImage(hMainInstance,MAKEINTRESOURCE((!aboutThread_mode ? IDB_SPLASH : IDB_PLATE)),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION); + m_imgoldbm=(HBITMAP)SelectObject(m_imgdc,m_imgbm); + m_source=(char *)GlobalAlloc(GPTR,img_w[aboutThread_mode]*img_h[aboutThread_mode]); + + if (m_imgbm && m_source) + { + memset(&m_bitmap, 0, sizeof(m_bitmap)); + m_bitmap.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + m_bitmap.bmi.bmiHeader.biPlanes = 1; + m_bitmap.bmi.bmiHeader.biBitCount = 8; + m_bitmap.bmi.bmiHeader.biCompression = BI_RGB; + m_bitmap.bmi.bmiHeader.biSizeImage = 0; + m_bitmap.bmi.bmiHeader.biClrUsed = 128; + m_bitmap.bmi.bmiHeader.biClrImportant = 128; + m_bitmap.bmi.bmiHeader.biWidth = img_w[aboutThread_mode]; + m_bitmap.bmi.bmiHeader.biHeight = -img_h[aboutThread_mode]; + m_bitmap.bmi.bmiHeader.biSizeImage = img_w[aboutThread_mode]*img_h[aboutThread_mode]; + + GetDIBits(m_imgdc,m_imgbm,0,img_h[aboutThread_mode],m_source,(BITMAPINFO *)&m_bitmap,DIB_RGB_COLORS); + GetDIBColorTable(m_imgdc,0,256,m_bitmap.bmi.bmiColors); + + SelectObject(m_imgdc, m_imgoldbm); + DeleteDC(m_imgdc); + DeleteObject(m_imgbm); + } + else + { + DeleteDC(m_imgdc); + if (m_imgbm) DeleteObject(m_imgbm); + if (m_source) GlobalFree(m_source); + return false; + } + + if (use_palette) + { + struct + { + LOGPALETTE logpal; + PALETTEENTRY palentries[255]; + } palette; + palette.logpal.palVersion = 0x300; + palette.logpal.palNumEntries = 128; + + for (c = 0; c < 128; c ++) + { + palette.logpal.palPalEntry[c].peRed = m_bitmap.bmi.bmiColors[c].rgbRed; + palette.logpal.palPalEntry[c].peGreen = m_bitmap.bmi.bmiColors[c].rgbGreen; + palette.logpal.palPalEntry[c].peBlue = m_bitmap.bmi.bmiColors[c].rgbBlue; + palette.logpal.palPalEntry[c].peFlags = 0; + } + m_haboutpal = CreatePalette((LOGPALETTE *)&palette.logpal); + } + + m_pitch=((r.right-r.left+3)&~3); + m_height=r.bottom-r.top; + m_bitmap.bmi.bmiHeader.biSizeImage = 0; + m_bitmap.bmi.bmiHeader.biClrUsed = 0; + m_bitmap.bmi.bmiHeader.biClrImportant = 0; + m_bitmap.bmi.bmiHeader.biWidth = m_pitch; + m_bitmap.bmi.bmiHeader.biHeight = -m_height; + m_bitmap.bmi.bmiHeader.biSizeImage = m_pitch*m_height; + m_hbm = CreateDIBSection(m_hdc,&m_bitmap.bmi,DIB_RGB_COLORS, &m_bitmap.data, NULL, 0); + + if (!m_hbm) + { + if (m_imgbm) DeleteObject(m_imgbm); + if (m_source) GlobalFree(m_source); + return 0; + } + m_oldhbm = (HBITMAP) SelectObject(m_hdc, m_hbm); + m_dib=(char*)m_bitmap.data; + { + for (int x = 0; x < img_h[aboutThread_mode]; x ++) + m_wmul[x]=x*img_w[aboutThread_mode]; + } + + return true; +} + + +bool AboutContext::Tick() +{ + if (aboutThread_kill) + return false; + + int tab[512] = {0}; + // Sleep(50); + { + int offs; + int x; + double max_d=sqrt((double)((m_pitch*m_pitch+m_height*m_height))/4.0f); + //int imax_d2=(int)(255.0/max_d*256.0); + int imax_d=(int)max_d; + double dpos; + + int thiswt=m_wt; + if (thiswt > 63) thiswt = 126-thiswt; + + dpos=1.0+sin(thiswt*M_PI/32.0); + + if (dpos < 1.0) dpos=0.5+dpos/2.0; + if (thiswt < 32) offs=thiswt*24; + else offs=(64-thiswt)*24; + if (imax_d > 512) return false; + + for (x = 0; x < imax_d; x ++) + { + tab[x]=(int) (pow(sin(x/(max_d-1)),dpos)*1.7*256.0*max_d/(x+1)) - offs; + if (tab[x]<0)tab[x]=-tab[x]; + } + + if (m_wt == 0) + { + if (m_wait++>=40) + { + m_wt++; + } + } + else + { + m_wait=0; + m_wt++; + } + m_wt&=127; + } + + { + int xsc=((!aboutThread_mode ? img_w[0]*180 : img_w[1]*360))/m_pitch; + int ysc=((!aboutThread_mode ? img_h[0]*200 : img_h[1]*500))/m_height; + int w2=m_pitch/2; + int h2=m_height/2; + char *out=m_dib; + int y; + if (m_wt) + { + a=!a; + // weird interlace shit + if (a && mode) + { + out+=m_pitch; + } + for (y = -h2+(mode?a:0); y < h2; y ++) + { + int x2=w2*w2+w2+y*y+256; + int dx2=-2*w2; + int yysc=y*ysc; + int xxsc=-w2*xsc; + int x=m_pitch; + while (x--) + { + int qd=tab[isqrt(x2)]; + int ow,oh; + x2+=dx2; + dx2+=2; + ow = img_w[aboutThread_mode]/2 + (qd*xxsc)/65536; + xxsc+=xsc; + oh = img_h[aboutThread_mode]/2 + (qd*yysc)/65536; + + if (ow < 0) ow=0; + else if (ow >= img_w[aboutThread_mode]) ow=img_w[aboutThread_mode]-1; + if (oh < 0) oh=0; + else if (oh >= img_h[aboutThread_mode]) oh=img_h[aboutThread_mode]-1; + + *out++=m_source[ow+m_wmul[oh]]; + } + + // weird interlace shit + if (mode) + { + y++; + out+=m_pitch; + } + } + } + else // copy, with optional rescale + { + int x; + int skipw=0; + int skiph=0; + + int dxp,dyp,xp,yp; + + skiph=(m_height-img_h[aboutThread_mode])/2; + skipw=(m_pitch-img_w[aboutThread_mode])/2; + + if (skipw <0) skipw=0; + if (skiph <0) skiph=0; + + dxp=(img_w[aboutThread_mode]<<16)/(m_pitch-skipw*2); + dyp=(img_h[aboutThread_mode]<<16)/(m_height-skiph*2); + yp=0; + for (y = 0; y < m_height; y ++) + { + if (y < skiph || y >= m_height - skiph) + { + memset(out,0,m_pitch); + out+=m_pitch; + } + else + { + char *in=m_source+(yp>>16)*img_w[aboutThread_mode]; + xp=0; + for (x = 0; x < m_pitch; x ++) + { + if (x < skipw || x >=m_pitch-skipw) + { + *out++=0; + } + else + { + *out++=in[xp>>16]; + xp+=dxp; + } + } + yp+=dyp; + } + } + } + } + + { + HWND hwnd=GetDlgItem(hwndDlg,IDC_ABOUTIMG); + if (hwnd) + { + HDC h=GetDC(hwnd); + if (h) + { + if (m_haboutpal) + { + SelectPalette(h,m_haboutpal,FALSE); + RealizePalette(h); + } + BitBlt(h,0,0,m_pitch,m_height,m_hdc,0,0,SRCCOPY); + ReleaseDC(hwnd,h); + } + } + } + + return true; +} + +void AboutContext::Quit() +{ + if (m_hbm) + { + if (m_hdc) SelectObject(m_hdc, m_oldhbm); + DeleteObject(m_hbm); + m_hbm = NULL; + m_oldhbm=NULL; + } + if (m_haboutpal) + { + DeleteObject(m_haboutpal); + m_haboutpal = NULL; + } + if (m_hdc) + { + DeleteDC(m_hdc); + m_hdc=NULL; + } + if (m_source) + { + GlobalFree((HGLOBAL)m_source); + m_source=NULL; + } +} + +static int AboutTickThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id) +{ + AboutContext *context = (AboutContext *)user_data; + TimerHandle t(handle); + if (context->Tick()) + { + t.Wait(50); + return 0; + } + else + { + context->Quit(); + delete context; + HANDLE event = (HANDLE)id; + SetEvent(event); + WASABI_API_THREADPOOL->RemoveHandle(0, handle); + t.Close(); + return 0; + } +} + +static int AboutThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id) +{ + AboutContext *context = new AboutContext; + if (context->Init((HWND)user_data)) + { + TimerHandle t; + WASABI_API_THREADPOOL->AddHandle(0, t, AboutTickThreadPoolFunc, context, id, 0); + t.Wait(50); + } + else + { + delete context; + HANDLE event = (HANDLE)id; + SetEvent(event); + } + return 0; +} +/* Window Proc for the 'winamp' tab of the about screen */ +static INT_PTR CALLBACK about1EggProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) +{ + switch(uMsg) + { + case WM_INITDIALOG: + { +#if 0 + static char ascii[]="\n\n ______ ____ ___/\\ _/\\_ _____ dro _____ <3 ______ /\\____ _______\n\ + \\_ \\/ \\/ \\_\\__/_\\ \\___ _\\ _ \\___ _\\ \\/ \\__\\ _ \\_\n\ + / / / / / \\/ |/ \\/ / / / / |/ /\n\ + / / / / / / / / / / / / ____/\n\ + \\______/\\________\\____/\\____/\\_____\\____/\\_____\\____\\____/\\____/\\____/\n\ + _________________________________________________________________ _________\n\ + (_________________________________________________________________\\\\\\_WINAMP_)\n\n\n\ + supplied by deadbeef\n\n\ + cracked by rOn\n\n\ + 32kb cool intro by lone"; + + int i=0; + FILE *fh; + fh=fopen("c:\\blah.c","wt"); + for(i=0;ascii[i];i++) + { + ascii[i]^=0x65; + fprintf(fh,"0x%x,",ascii[i]); + if((i&31)==31) fprintf(fh,"\n"); + } + fclose(fh); +#else + static char ascii[]={ + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 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, + 0x56,0x57,0xe,0x7,0x45,0x6,0xa,0xa,0x9,0x45,0xc,0xb,0x11,0x17,0xa,0x45,0x7,0x1c,0x45,0x9,0xa,0xb,0x0, + }; + static int dexored=0; + if(!dexored) + { + int i=0; + for(i=0;i<sizeof(ascii);i++) ascii[i]^=0x65; + dexored=1; + } +#endif + SetDlgItemTextA(hwndDlg,IDC_ASCII,ascii); + } + return 1; + case WM_LBUTTONDBLCLK: + { + EndDialog(hwndDlg,0); + ShowWindow(GetDlgItem(GetParent(hwndDlg),IDC_ABOUTIMG),SW_NORMAL); + } + break; + } + return 0; +} + +/* Window proc for the about screen (i.e. this one handles the tab changes */ +static BOOL CALLBACK about1Proc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) +{ + static HANDLE hThread; + static HWND egg_wnd; + if (uMsg == WM_INITDIALOG) + { + if (!hThread) + { + aboutThread_kill=0; + aboutThread_mode=0; + hThread = CreateEvent(NULL, TRUE, FALSE, NULL); + WASABI_API_THREADPOOL->RunFunction(0, AboutThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, 0); + } + { + wchar_t buf[2048] = {0}, buf2[2048] = {0}, buf3[256] = {0}, + *t1 = 0, *t2 = 0, *t3 = 0; + GetDlgItemTextW(hwndDlg,IDC_ABOUTTEXT,buf,ARRAYSIZE(buf)); + StringCchPrintfW(buf2,2048,buf,(buf3[0] ? buf3 : (t1 = AutoWideDup(app_version_string))), + (t2 = AutoWideDup(APP_VERSION_PLATFORM)), (t3 = AutoWideDup(app_date))); + SetDlgItemTextW(hwndDlg, IDC_ABOUTTEXT, buf2); + link_startsubclass(hwndDlg, IDC_WINAMPLINK); + if (t1) free(t1); + if (t2) free(t2); + if (t3) free(t3); + } + return TRUE; + } + if (uMsg == WM_QUERYNEWPALETTE) + { + if (m_haboutpal) + { + HDC hdc = GetWindowDC(hwndDlg); + SelectPalette(hdc,m_haboutpal,FALSE); + RealizePalette(hdc); + InvalidateRect(hwndDlg,NULL,FALSE); + ReleaseDC(hwndDlg,hdc); + return 1; + } + return 0; + } + if (uMsg == WM_PALETTECHANGED) + { + if (m_haboutpal) + { + HDC hdc = GetWindowDC(hwndDlg); + SelectPalette(hdc,m_haboutpal,FALSE); + RealizePalette(hdc); + UpdateColors(hdc); + ReleaseDC(hwndDlg,hdc); + return 1; + } + return 0; + } + if (uMsg == WM_DESTROY) + { + if (hThread) + { + aboutThread_kill=1; + WaitForSingleObject(hThread,INFINITE); + CloseHandle(hThread); + hThread=NULL; + } + } + if (uMsg == WM_COMMAND) + { + switch (LOWORD(wParam)) + { + case IDC_WINAMPLINK: + { + wchar_t homepage[1024] = {0}; + if (config_langpack[0]) + { + getStringW(IDS_LOCALIZED_HOMEPAGE, homepage, 1024); + } + if (homepage[0]) + myOpenURL(hwndDlg, homepage); + else + myOpenURL(hwndDlg,L"http://www.winamp.com/"); + } + return 0; + } + } + if (uMsg == WM_LBUTTONDBLCLK) + { + if ((GetAsyncKeyState(VK_SHIFT)&0x8000) && !(GetAsyncKeyState(VK_CONTROL)&0x8000)) + { + ShowWindow(GetDlgItem(hwndDlg,IDC_ABOUTIMG),SW_HIDE); + if (!IsWindow(egg_wnd)) + { + egg_wnd = LPCreateDialogW(IDD_NEWABOUT1EGG,hwndDlg,about1EggProc); + } + ShowWindow(egg_wnd, SW_SHOW); + } + else + { + if ((GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_SHIFT)&0x8000)) + { + if (hThread) + { + aboutThread_kill=1; + WaitForSingleObject(hThread,INFINITE); + CloseHandle(hThread); + hThread=NULL; + aboutThread_kill=0; + aboutThread_mode=!aboutThread_mode; + hThread = CreateEvent(NULL, TRUE, FALSE, NULL); + WASABI_API_THREADPOOL->RunFunction(0, AboutThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, 0); + } + } + ShowWindow(GetDlgItem(hwndDlg,IDC_ABOUTIMG),SW_SHOW); + } + } + link_handledraw(hwndDlg,uMsg,wParam,lParam); + return 0; +} + +static volatile int creditThread_kill; +static HPALETTE m_hcreditspal; + +/* this thread handles the 3d credits rendering (this one does some busywork and housecleaning, actual rendering done in creditsrend.c) */ +class CreditsContext +{ +public: + bool Init(HWND _hwndDlg); + bool Tick(int &wait_time); + void Quit(); + +private: + HDC m_hdc; + HBITMAP m_hbm,m_oldhbm; + int m_pitch,m_height; + char *m_dib; +char pal[768]; + struct + { + BITMAPINFO bmi; + RGBQUAD more_bmiColors[255]; + } m_bitmap; + int c,use_palette; + HWND hwndDlg; +}; + +bool CreditsContext::Init(HWND _hwndDlg) +{ + hwndDlg = _hwndDlg; + Tataki::Init(WASABI_API_SVC); + m_hcreditspal = 0; + m_hdc = 0; + m_hbm = 0; + + RECT r={0,}; + memset(&m_bitmap, 0, sizeof(m_bitmap)); + + GetWindowRect(hwndDlg,&r); + r.right=r.right-r.left; + r.bottom=r.bottom-r.top; + HDC hdc=GetWindowDC(hwndDlg); + if (!hdc) + return false; + use_palette = (GetDeviceCaps(hdc,RASTERCAPS)&RC_PALETTE)?1:0; + m_hdc = CreateCompatibleDC(NULL); + ReleaseDC(hwndDlg,hdc); + + m_pitch=((r.right+3)&~3); + m_height=r.bottom; + if (m_pitch < 4) m_pitch=4; + if (m_height < 4) m_height=4; + // if (m_pitch > GetSystemMetrics(SM_CXSCREEN)) m_pitch=GetSystemMetrics(SM_CXSCREEN); + // if (m_height > GetSystemMetrics(SM_CYSCREEN)) m_height=GetSystemMetrics(SM_CYSCREEN); + render_init(m_pitch,m_height,pal); + + { + struct + { + LOGPALETTE logpal; + PALETTEENTRY palentries[255]; + } palette; + palette.logpal.palVersion = 0x300; + palette.logpal.palNumEntries = 220; + for (c = 0; c < 256; c ++) + { + palette.logpal.palPalEntry[c].peRed = pal[c*3]; + palette.logpal.palPalEntry[c].peGreen = pal[c*3+1]; + palette.logpal.palPalEntry[c].peBlue = pal[c*3+2]; + palette.logpal.palPalEntry[c].peFlags = PC_NOCOLLAPSE; + m_bitmap.bmi.bmiColors[c].rgbRed=pal[c*3]; + m_bitmap.bmi.bmiColors[c].rgbGreen=pal[c*3+1]; + m_bitmap.bmi.bmiColors[c].rgbBlue=pal[c*3+2]; + m_bitmap.bmi.bmiColors[c].rgbReserved=0; + } + if (use_palette) + m_hcreditspal = CreatePalette((LOGPALETTE *)&palette.logpal); + } + + + m_bitmap.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + m_bitmap.bmi.bmiHeader.biPlanes = 1; + m_bitmap.bmi.bmiHeader.biBitCount = 8; + m_bitmap.bmi.bmiHeader.biCompression = BI_RGB; + m_bitmap.bmi.bmiHeader.biSizeImage = 0; + m_bitmap.bmi.bmiHeader.biClrImportant = 0; + m_bitmap.bmi.bmiHeader.biClrUsed = 256; + m_bitmap.bmi.bmiHeader.biWidth = m_pitch; + m_bitmap.bmi.bmiHeader.biHeight = -m_height; + m_bitmap.bmi.bmiHeader.biSizeImage = m_pitch*m_height; + m_hbm = CreateDIBSection(m_hdc,&m_bitmap.bmi,DIB_RGB_COLORS, (void**)&m_dib, NULL, 0); + m_oldhbm = (HBITMAP) SelectObject(m_hdc, m_hbm); + return (m_hbm && m_dib); +} + +void CreditsContext::Quit() +{ + if (m_hbm) + { + if (m_hdc) SelectObject(m_hdc, m_oldhbm); + DeleteObject(m_hbm); + m_hbm = NULL; + m_oldhbm=NULL; + } + if (m_hcreditspal) + { + DeleteObject(m_hcreditspal); + m_hcreditspal = NULL; + } + if (m_hdc) + { + DeleteDC(m_hdc); + m_hdc=NULL; + } + render_quit(); + Tataki::Quit(); +} + +bool CreditsContext::Tick(int &wait_time) +{ + if (creditThread_kill) + return false; + + unsigned int thist=GetTickCount(); + render_render((unsigned char*)m_dib, m_hdc); + { + HDC h=GetDC(hwndDlg); + if (h) + { + if (m_hcreditspal) + { + SelectPalette(h,m_hcreditspal,FALSE); + RealizePalette(h); + } + BitBlt(h,0,0,m_pitch,m_height,m_hdc,0,0,SRCCOPY); + ReleaseDC(hwndDlg,h); + } + } + thist=GetTickCount()-thist; + if (thist > 28) thist=28; + wait_time = 30-thist; + return true; +} + +static int CreditsTickThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id) +{ + CreditsContext *context = (CreditsContext *)user_data; + TimerHandle t(handle); + int wait_time=30; + if (context->Tick(wait_time)) + { + t.Wait(wait_time); + return 0; + } + else + { + context->Quit(); + delete context; + HANDLE event = (HANDLE)id; + SetEvent(event); + WASABI_API_THREADPOOL->RemoveHandle(0, handle); + t.Close(); + return 0; + } +} + +static int CreditThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id) +{ + CreditsContext *context = new CreditsContext; + if (context->Init((HWND)user_data)) + { + TimerHandle t; + WASABI_API_THREADPOOL->AddHandle(0, t, CreditsTickThreadPoolFunc, context, id, api_threadpool::FLAG_LONG_EXECUTION); + t.Wait(30); + } + else + { + delete context; + HANDLE event = (HANDLE)id; + SetEvent(event); + } + return 0; +} + +/* Window Proc for the 'credits' tab of the about screen */ +static BOOL CALLBACK creditProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) +{ + static int g_fullscreen=0; + static RECT rsave; + static HWND hOldParent; + static int oldstyle; + static HANDLE hThread; + if (uMsg == WM_LBUTTONDBLCLK) + { + render_togglecredits(); + return 0; + } + if (uMsg == WM_KEYDOWN && g_fullscreen) + { + if (wParam == VK_ESCAPE) + { + PostMessageW(hwndDlg,WM_LBUTTONDOWN,0,0); + } + else PostMessageW(hMainWindow,uMsg,wParam,lParam); + } + if ((uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK) && g_fullscreen) + { + if (hThread) + { + creditThread_kill=1; + WaitForSingleObject(hThread,INFINITE); + CloseHandle(hThread); + hThread = 0; + if (g_fullscreen) + { + RECT r=rsave; + ScreenToClient(hOldParent,(LPPOINT)&r); + ScreenToClient(hOldParent,(LPPOINT)&r+1); + SetWindowLong(hwndDlg,GWL_STYLE,oldstyle); + SetParent(hwndDlg,hOldParent); + SetWindowPos(hwndDlg,0,r.left,r.top,r.right-r.left,r.bottom-r.top,SWP_NOZORDER); + } + } + g_fullscreen=0; + creditThread_kill=0; + hThread = CreateEvent(NULL, TRUE, FALSE, NULL); + WASABI_API_THREADPOOL->RunFunction(0, CreditThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, api_threadpool::FLAG_LONG_EXECUTION); + } + else if (uMsg == WM_RBUTTONDBLCLK && !g_fullscreen) + { + RECT r; + if (hThread) + { + creditThread_kill=1; + WaitForSingleObject(hThread,INFINITE); + CloseHandle(hThread); + hThread = 0; + } + g_fullscreen=1; + GetWindowRect(hwndDlg,&rsave); + oldstyle=GetWindowLongW(hwndDlg,GWL_STYLE); + hOldParent=SetParent(hwndDlg,NULL); + + SetWindowLong(hwndDlg,GWL_STYLE,WS_POPUP|WS_VISIBLE); + + getViewport(&r,hwndDlg,1,NULL); + + SetWindowPos(hwndDlg, HWND_TOPMOST, r.left, r.top, r.right, r.bottom, SWP_DRAWFRAME); + creditThread_kill=0; + hThread = CreateEvent(NULL, TRUE, FALSE, NULL); + WASABI_API_THREADPOOL->RunFunction(0, CreditThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, api_threadpool::FLAG_LONG_EXECUTION); + // go fullscreen + } + if (uMsg == WM_INITDIALOG) + { + if (!hThread) + { + g_fullscreen=0; + creditThread_kill=0; + hThread = CreateEvent(NULL, TRUE, FALSE, NULL); + WASABI_API_THREADPOOL->RunFunction(0, CreditThreadPoolFunc, (void *)hwndDlg, (intptr_t)hThread, api_threadpool::FLAG_LONG_EXECUTION); + } + return TRUE; + } + if (uMsg == WM_QUERYNEWPALETTE) + { + if (m_hcreditspal) + { + HDC hdc = GetWindowDC(hwndDlg); + SelectPalette(hdc,m_hcreditspal,FALSE); + RealizePalette(hdc); + InvalidateRect(hwndDlg,NULL,FALSE); + ReleaseDC(hwndDlg,hdc); + return 1; + } + return 0; + } + if (uMsg == WM_PALETTECHANGED) + { + if (m_hcreditspal) + { + HDC hdc = GetWindowDC(hwndDlg); + SelectPalette(hdc,m_hcreditspal,FALSE); + RealizePalette(hdc); + UpdateColors(hdc); + ReleaseDC(hwndDlg,hdc); + return 1; + } + return 0; + } + if (uMsg == WM_DESTROY) + { + if (hThread) + { + creditThread_kill=1; + WaitForSingleObject(hThread,INFINITE); + CloseHandle(hThread); + hThread=NULL; + } + } + return 0; +} + +static BOOL CALLBACK translationProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) +{ + switch (uMsg) + { + case WM_INITDIALOG: + { + // only attempt set it to show a hand cursor if it's an ownerdraw button + if(GetWindowLongPtrW(GetDlgItem(hwndDlg, IDC_AUTHOR_HOMEPAGE), GWL_STYLE) & BS_OWNERDRAW) + { + link_startsubclass(hwndDlg, IDC_AUTHOR_HOMEPAGE); + } + if(GetWindowLongPtrW(GetDlgItem(hwndDlg, IDC_AUTHOR_HOMEPAGE2), GWL_STYLE) & BS_OWNERDRAW) + { + link_startsubclass(hwndDlg, IDC_AUTHOR_HOMEPAGE2); + } + } + break; + + case WM_COMMAND: + if(LOWORD(wParam) == IDCANCEL) + { + DestroyWindow(about_hwnd); + } + else if (LOWORD(wParam) == IDC_AUTHOR_HOMEPAGE) + { + wchar_t homepage[1024] = {0}; + getStringW(IDS_AUTHOR_HOMEPAGE, homepage, 1024); + myOpenURL(hwndDlg, homepage); + } + else if (LOWORD(wParam) == IDC_AUTHOR_HOMEPAGE2) + { + wchar_t homepage[1024] = {0}; + getStringW(IDS_AUTHOR_HOMEPAGE2, homepage, 1024); + myOpenURL(hwndDlg, homepage); + } + break; + } + link_handledraw(hwndDlg,uMsg,wParam,lParam); + return 0; +} |