/** (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 #include "../nu/threadname.h" #include "resource.h" #include #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 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;iRunFunction(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; }