1 /*
2   LICENSE
3   -------
4 Copyright 2005-2013 Nullsoft, Inc.
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9 
10   * Redistributions of source code must retain the above copyright notice,
11     this list of conditions and the following disclaimer.
12 
13   * Redistributions in binary form must reproduce the above copyright notice,
14     this list of conditions and the following disclaimer in the documentation
15     and/or other materials provided with the distribution.
16 
17   * Neither the name of Nullsoft nor the names of its contributors may be used to
18     endorse or promote products derived from this software without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include "api.h"
31 #include "pluginshell.h"
32 #include "resource.h"
33 #include "utility.h"
34 #include "defines.h"
35 #include "shell_defines.h"
36 #include "vis.h"
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <math.h>
40 #include <multimon.h>
41 #include <commctrl.h>
42 #include <shellapi.h>
43 #include <strsafe.h>
44 
45 #define PREFERRED_FORMAT D3DFMT_X8R8G8B8
46 #define MAX_PROPERTY_PAGES 8
47 #define MAX_DISPLAY_ADAPTERS 16
48 #define MAX_MAX_FPS 120
49 #define MAX_DISPLAY_MODES 1024
50 
51 extern winampVisModule mod1;
52 
53 IDirect3D9* g_lpDX;
54 HMODULE     g_hmod_d3d9;
55 HMODULE     g_hmod_d3dx9;
56 D3DADAPTER_IDENTIFIER9 g_disp_adapter_w[MAX_DISPLAY_ADAPTERS];   // NOTE: indices into this list might not equal the ordinal adapter indices!
57 D3DADAPTER_IDENTIFIER9 g_disp_adapter_fs[MAX_DISPLAY_ADAPTERS];  // NOTE: indices into this list might not equal the ordinal adapter indices!
58 D3DADAPTER_IDENTIFIER9 g_disp_adapter_dm[MAX_DISPLAY_ADAPTERS];  // NOTE: indices into this list might not equal the ordinal adapter indices!
59 D3DDISPLAYMODE         g_disp_mode[MAX_DISPLAY_MODES];
60 HWND        g_config_hwnd;
61 HWND        g_subwnd;
62 int         g_num_disp_modes;
63 int         g_nTab;
64 int         g_ignore_clicks;
65 int         g_zero_display_modes_warning_given;
66 int         g_proppage_id[MAX_PROPERTY_PAGES];
67 
GetCurrentDisplayMode(D3DDISPLAYMODE * pMode)68 void GetCurrentDisplayMode(D3DDISPLAYMODE *pMode)
69 {
70     if (!pMode)
71         return;
72 
73     DEVMODE dm;
74     dm.dmSize = sizeof(dm);
75     dm.dmDriverExtra = 0;
76     if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
77         return;
78 
79     pMode->Width  = dm.dmPelsWidth;
80     pMode->Height = dm.dmPelsHeight;
81     pMode->Format = (dm.dmBitsPerPel==16) ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
82     pMode->RefreshRate = dm.dmDisplayFrequency;
83 }
84 
InitConfig(HWND hDialogWnd)85 bool CPluginShell::InitConfig(HWND hDialogWnd)
86 {
87     // ******* do initialization of global variables HERE *******
88     // ******* do initialization of global variables HERE *******
89     // ******* do initialization of global variables HERE *******
90 
91     g_lpDX = NULL;
92     g_hmod_d3d9 = NULL;
93 	g_hmod_d3dx9 = NULL;
94     g_num_disp_modes = 0;
95     g_config_hwnd = hDialogWnd;
96     g_ignore_clicks = 1;
97     g_subwnd = NULL;
98     g_nTab   = 0;
99     g_zero_display_modes_warning_given = 0;
100 
101     g_proppage_id[0] = IDD_PROPPAGE_1;
102     g_proppage_id[1] = IDD_PROPPAGE_2;
103     g_proppage_id[2] = IDD_PROPPAGE_3;
104     g_proppage_id[3] = IDD_PROPPAGE_4;
105     g_proppage_id[4] = IDD_PROPPAGE_5;
106     g_proppage_id[5] = IDD_PROPPAGE_6;
107     g_proppage_id[6] = IDD_PROPPAGE_7;
108     g_proppage_id[7] = IDD_PROPPAGE_8;
109 
110     // ******* do initialization of global variables HERE *******
111     // ******* do initialization of global variables HERE *******
112     // ******* do initialization of global variables HERE *******
113 
114     return true;
115 }
116 
EndConfig()117 void CPluginShell::EndConfig()
118 {
119     SafeRelease(g_lpDX);
120 
121     if (g_subwnd)
122     {
123 		DestroyWindow(g_subwnd);
124 		g_subwnd = NULL;
125     }
126 
127     if (g_hmod_d3d9)
128     {
129         FreeLibrary(g_hmod_d3d9);
130         g_hmod_d3d9 = NULL;
131     }
132 		if (g_hmod_d3dx9)
133     {
134         g_hmod_d3dx9 = NULL;
135     }
136 }
137 
AddButton(int pos,HWND tabctrl,LPWSTR szButtonText)138 static bool AddButton(int pos, HWND tabctrl, LPWSTR szButtonText)
139 {
140     if (szButtonText && szButtonText[0] && szButtonText[0] != L' ')
141     {
142         TCITEMW tie = {0};
143         tie.mask = TCIF_TEXT | TCIF_IMAGE;
144         tie.iImage = -1;
145         tie.pszText = szButtonText;
146 
147         if (SendMessageW(tabctrl, TCM_INSERTITEMW, pos, (LPARAM)&tie) == -1)
148             return false;
149     }
150     return true;
151 }
152 
UpdateAdapters(int screenmode)153 void CPluginShell::UpdateAdapters(int screenmode)
154 {
155     int i;
156 
157     if (!g_lpDX) return;
158 
159     int nDispAdapters = 0;
160 
161     HWND ctrl;
162     GUID* pGUID = NULL;
163     char deviceName[256];
164     switch(screenmode)
165     {
166     case FULLSCREEN:
167         ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_FS);
168         pGUID = &m_adapter_guid_fullscreen;
169         StringCbCopy(deviceName, sizeof(deviceName), m_adapter_devicename_fullscreen);
170         break;
171     case WINDOWED:
172         ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_W);
173         pGUID = &m_adapter_guid_windowed;
174         StringCbCopy(deviceName, sizeof(deviceName), m_adapter_devicename_windowed);
175         break;
176     /*case FAKE_FULLSCREEN:
177         ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_FFS);
178         pGUID = &m_adapter_guid_fake_fullscreen;
179         strcpy(deviceName, m_adapter_devicename_fake_fullscreen);
180         break;*/
181     case DESKTOP:
182         ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_DMS);
183         pGUID = &m_adapter_guid_desktop;
184         StringCbCopy(deviceName, sizeof(deviceName), m_adapter_devicename_desktop);
185         break;
186     }
187 
188     // clear the combo box
189     SendMessage( ctrl, CB_RESETCONTENT, 0, 0);
190 
191     // repopulate the combo box with a list of adapters
192     {
193         char szDesc[1024];
194 
195         D3DADAPTER_IDENTIFIER9* global_adapter_list;
196         switch(screenmode)
197         {
198         case FULLSCREEN:
199             global_adapter_list = g_disp_adapter_fs;
200             break;
201         case WINDOWED:
202             global_adapter_list = g_disp_adapter_w;
203             break;
204         /*case FAKE_FULLSCREEN:
205             global_adapter_list = g_disp_adapter_w;     // [sic]
206             break;*/
207         case DESKTOP:
208             global_adapter_list = g_disp_adapter_dm;
209             break;
210         }
211 
212         int nAdapters = g_lpDX->GetAdapterCount();
213 
214         // re-populate it:
215 
216         wchar_t szDebugFile[MAX_PATH];
217         StringCbCopyW(szDebugFile, sizeof(szDebugFile), m_szConfigIniFile);
218         wchar_t* p = wcsrchr(szDebugFile, L'\\');
219         if (p)
220         {
221             lstrcpyW(p+1, ADAPTERSFILE);
222             FILE* f = _wfopen(szDebugFile, L"w");
223             if (f)
224             {
225                 DWORD winamp_version = SendMessage(GetWinampWindow(),WM_WA_IPC,0,0);
226                 fprintf(f, "Winamp version = 0x%04X\n", winamp_version);
227                 fprintf(f, "Plugin long name = \"%s\", version=%d, subversion=%d\n", LONGNAME, INT_VERSION, INT_SUBVERSION);
228                 fprintf(f, "Enumeration of Display Adapters:\n");
229                 //fprintf(f, "...this is a temporary debug file created by MilkDrop 2.\n");
230                 //fprintf(f, "...don't worry - the final release of the plug-in will NOT generate this file.\n");
231                 for (i=0; i<nAdapters && nDispAdapters<MAX_DISPLAY_ADAPTERS; i++)
232                 {
233                     if (g_lpDX->GetAdapterIdentifier(i, /*D3DENUM_NO_WHQL_LEVEL*/ 0, &global_adapter_list[nDispAdapters]) == D3D_OK)
234                     {
235                         // Now get the caps, and filter out any graphics cards that can't
236                         // do, say, gouraud shading:
237 
238                         int adapter_ok = 1;
239 
240                         /*
241                         D3DCAPS9 caps;
242                         if (g_lpDX->GetDeviceCaps(i, D3DDEVTYPE_HAL, &caps)==D3D_OK)
243                         {
244                             // check the caps here, make sure the device is up to par.  example:
245                             if (caps.ShadeCaps & D3DPSHADECAPS_COLORGOURAUDRGB)
246                               adapter_ok = 0;
247                         }
248                         */
249 
250                         if (f) {
251                             fprintf(f, "%d. Driver=%s\n", nDispAdapters+1, global_adapter_list[nDispAdapters].Driver);
252                             fprintf(f, "    Description=%s\n",      global_adapter_list[nDispAdapters].Description);
253                             fprintf(f, "    DeviceName=%s\n",       global_adapter_list[nDispAdapters].DeviceName);
254                             fprintf(f, "    DriverVersion=0x%08X (%d)\n",global_adapter_list[nDispAdapters].DriverVersion);
255                             fprintf(f, "    VendorId=%d\n",         global_adapter_list[nDispAdapters].VendorId);
256                             fprintf(f, "    DeviceId=%d\n",         global_adapter_list[nDispAdapters].DeviceId);
257                             fprintf(f, "    SubSysId=0x%08X\n",         global_adapter_list[nDispAdapters].SubSysId);
258                             fprintf(f, "    Revision=%d\n",         global_adapter_list[nDispAdapters].Revision);
259                             //fprintf(f, "    DeviceIdentifier=0x%08X\n", global_adapter_list[nDispAdapters].DeviceIdentifier);
260                              char szGuidText[512];
261                              GuidToText(&global_adapter_list[nDispAdapters].DeviceIdentifier, szGuidText, sizeof(szGuidText));
262                             fprintf(f, "    WHQLLevel=%d\n",        global_adapter_list[nDispAdapters].WHQLLevel);
263                             fprintf(f, "    GUID=%s\n", szGuidText);
264                         }
265 
266                         if (adapter_ok)
267                         {
268                             sprintf(szDesc, "%d. %s   [%s]", nDispAdapters+1, global_adapter_list[nDispAdapters].Description, global_adapter_list[nDispAdapters].Driver);
269                             SendMessage( ctrl, CB_ADDSTRING, nDispAdapters, (LPARAM)szDesc);
270                             nDispAdapters++;
271                         }
272                     }
273                 }
274                 fclose(f);
275             }
276         }
277 
278         // set selection(s):
279         // find i where global_adapter_list[i].DeviceIdentifier is the same as last time,
280         // and select it.
281         int found = 0;
282         for (i=0; i<nDispAdapters; i++)
283         {
284             if (!found &&
285                 memcmp(&global_adapter_list[i].DeviceIdentifier, pGUID, sizeof(GUID))==0 &&
286                 !strcmp(global_adapter_list[i].DeviceName, deviceName)
287                 )
288             {
289                 SendMessage( ctrl, CB_SETCURSEL, i, 0);
290                 found = 1;
291             }
292         }
293         if (!found)
294             SendMessage( ctrl, CB_SETCURSEL, 0, 0);
295     }
296 
297     if (screenmode == FULLSCREEN)
298         UpdateFSAdapterDispModes();
299     else
300         UpdateDispModeMultiSampling(screenmode);
301 }
302 
UpdateFSAdapterDispModes()303 void CPluginShell::UpdateFSAdapterDispModes()   // (fullscreen only)
304 {
305     wchar_t szfmt[256], str[256];
306     int i;
307     HWND hwnd_listbox = GetDlgItem( g_subwnd, IDC_DISP_MODE );
308 
309     int nVideoModesTotal = 0;
310     if (!g_lpDX) return;
311     int nAdapterOrdinal = GetCurrentlySelectedAdapter(FULLSCREEN);
312     nVideoModesTotal = g_lpDX->GetAdapterModeCount(nAdapterOrdinal, PREFERRED_FORMAT);
313 
314     if (nVideoModesTotal <= 0 && !g_zero_display_modes_warning_given)
315     {
316         g_zero_display_modes_warning_given = 1;
317 		wchar_t title[64];
318         MessageBoxW(g_config_hwnd, WASABI_API_LNGSTRINGW(IDS_GRAPHICS_SUBSYSTEM_IS_TEMPORARILY_UNSTABLE),
319 				   WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_WARNING, title, 64),
320 				   MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
321     }
322 
323     // clear the combo box
324     SendMessage( hwnd_listbox, CB_RESETCONTENT, 0, 0);
325 
326     int nAdded = 0;
327 
328     // re-populate it:
329     for (i=0; i<nVideoModesTotal; i++)
330     {
331         if (nAdded >= MAX_DISPLAY_MODES)
332             break;
333 
334         // get info for display mode into g_disp_mode[nAdded]
335         if (g_lpDX->EnumAdapterModes(nAdapterOrdinal, PREFERRED_FORMAT, i, &g_disp_mode[nAdded]) != D3D_OK)
336             continue;
337 
338         // add to combo box
339         int bpp = 0;
340         switch(g_disp_mode[nAdded].Format)
341         {
342         default:
343         case D3DFMT_UNKNOWN      : WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN, szfmt, 256);   bpp=0;  break;
344         case D3DFMT_R8G8B8       : lstrcpynW(szfmt, L"RGB-888", 256);  bpp=32; break;
345         case D3DFMT_A8R8G8B8     : lstrcpynW(szfmt, L"ARGB-8888", 256); bpp=32; break;
346         case D3DFMT_X8R8G8B8     : lstrcpynW(szfmt, L"XRGB-8888", 256); bpp=32; break;
347         case D3DFMT_R5G6B5       : lstrcpynW(szfmt, L"RGB-565", 256);   bpp=16; break;
348         case D3DFMT_X1R5G5B5     : lstrcpynW(szfmt, L"XRGB-1555", 256);  bpp=16; break;
349         case D3DFMT_A1R5G5B5     : lstrcpynW(szfmt, L"ARGB-1555", 256);  bpp=16; break;
350         case D3DFMT_A4R4G4B4     : lstrcpynW(szfmt, L"ARGB-4444", 256);  bpp=16; break;
351         case D3DFMT_X4R4G4B4     : lstrcpynW(szfmt, L"XRGB-4444", 256);  bpp=16; break;
352         }
353         swprintf(str, L" %s,  %4d x %4d,  %3d %s ",
354 				 szfmt, g_disp_mode[nAdded].Width,
355 				 g_disp_mode[nAdded].Height,
356 				 g_disp_mode[nAdded].RefreshRate,
357 				 WASABI_API_LNGSTRINGW(IDS_HZ));
358 
359         /*
360         #ifdef DONT_ALLOW_8BIT_FULLSCREEN
361             if (bpp==8) continue;
362         #endif
363         #ifdef DONT_ALLOW_16_24_32_BIT_FULLSCREEN
364             if (bpp==16 || bpp==24 || bpp==32) continue;
365         #endif
366         */
367 
368         int nPos = SendMessageW( hwnd_listbox, CB_ADDSTRING, 0, (LPARAM)str);
369 
370         // keep a record of the original index, because the combo box SORTS the data:
371         SendMessage( hwnd_listbox, CB_SETITEMDATA, nPos, i);
372 
373         nAdded++;
374     }
375 
376     g_num_disp_modes = nAdded;
377 
378     // now set selection, based on best match to prev. video mode.
379     int found = 0;
380 
381     // Fallback order:
382     // 0. exact match (4 params)   w,h,r,f
383     // 1. ignore refresh rate, but still heed color format
384     // 2. heed only w,h, and if desired_mode.Format is UNKNOWN,
385     //        try for a 16-bpp color format and 60 Hz
386     // 3. heed only w,h, and if desired_mode.Format is UNKNOWN,
387     //        try for a 16-bpp color format at any Hz
388     // 4. heed only w,h.
389 
390     D3DDISPLAYMODE desired_mode = m_disp_mode_fs;
391 
392     assert(desired_mode.Format != D3DFMT_UNKNOWN);
393     // this should never happen anymore, now that we set smarter default FS display mode
394     // (to match the current display mode) in PluginShell.cpp's PluginPreInitialize().
395     /*if (desired_mode.Format==D3DFMT_UNKNOWN)
396     {
397         GetCurrentDisplayMode(&desired_mode);
398 
399         // first-time config: try to find a video mode that matches our ideal.
400 		// do many passes until we find one, each time relaxing more constraints.
401 		// outline of the passes:
402 
403 		// PASS  MATCH:
404         // 0. w,h,r,16bpp
405         // 1. w,h,-,16bpp
406         // 2. w,h,r,-
407         // 3. w,h,-,-
408         // 4. -,-,-,-
409         for (int rep=0; rep<5; rep++)
410         {
411             for (i=0; i<g_num_disp_modes && !found; i++)
412             {
413                 // we have to remap here, because the combo box SORTED the data:
414                 int id = SendMessage( hwnd_listbox, CB_GETITEMDATA, i, 0);
415 
416                 bool bDesiredBitDepth = (
417                                 (g_disp_mode[id].Format == D3DFMT_R8G8B8  ) ||
418                                 (g_disp_mode[id].Format == D3DFMT_A8R8G8B8) ||
419                                 (g_disp_mode[id].Format == D3DFMT_X8R8G8B8)
420                                         );
421 
422                 bool bMatch = true;
423 
424                 if (rep<=3 && desired_mode.Width!=g_disp_mode[id].Width)
425                     bMatch = false;
426                 if (rep<=3 && desired_mode.Height!=g_disp_mode[id].Height)
427                     bMatch = false;
428                 if ((rep==0 || rep==2) && desired_mode.RefreshRate!=g_disp_mode[id].RefreshRate)
429                     bMatch = false;
430                 if (rep<=1 && !bDesiredBitDepth)
431                     bMatch = false;
432 
433                 if (bMatch)
434                 {
435                     SendMessage( hwnd_listbox, CB_SETCURSEL, i, 0);
436                     found = 1;
437                 }
438             }
439         }
440 
441         // if no match could be found, select #0.
442         if (!found)
443             SendMessage( hwnd_listbox, CB_SETCURSEL, 0, 0);
444     }
445     else
446     */
447     {
448         // find best match to prev. selection.
449 		// do many passes until we find one, each time relaxing more constraints.
450 		// outline of the passes:
451 
452         int bpp_desired = 0;
453         switch(desired_mode.Format)
454         {
455         case D3DFMT_R8G8B8  : bpp_desired = 32; break;
456         case D3DFMT_A8R8G8B8: bpp_desired = 32; break;
457         case D3DFMT_X8R8G8B8: bpp_desired = 32; break;
458         case D3DFMT_R5G6B5  : bpp_desired = 16; break;
459         case D3DFMT_X1R5G5B5: bpp_desired = 16; break;
460         case D3DFMT_A1R5G5B5: bpp_desired = 16; break;
461         case D3DFMT_A4R4G4B4: bpp_desired = 16; break;
462         case D3DFMT_R3G3B2  : bpp_desired =  8; break;
463         case D3DFMT_A8R3G3B2: bpp_desired = 16; break;
464         case D3DFMT_X4R4G4B4: bpp_desired = 16; break;
465         }
466 
467 		// rep   MATCH:
468 		//  0. w,h,r,f
469         //  1. w,h,-,f
470         //  2. w,h,r,-         pass:
471         //  3. w,h,-,-           -on pass 0, for 'f', match exact format
472         //  4. 8,6,r,f           -on pass 1, for 'f', just match # of bits per pixel
473         //  5. 8,6,-,f              (more relaxed match)
474         //  6. 8,6,r,-
475         //  7. 8,6,-,-
476         //  8. -,-,r,f
477         //  9. -,-,-,f
478         // 10. -,-,r,-
479         // 11. -,-,-,-
480         for (int rep=0; rep<12 && !found; rep++)
481         {
482             for (int pass=0; pass<2 && !found; pass++)
483             {
484                 for (i=0; i<g_num_disp_modes && !found; i++)
485                 {
486                     // we have to remap here, because the combo box SORTED the data:
487                     int id = SendMessage( hwnd_listbox, CB_GETITEMDATA, i, 0);
488 
489                     int bpp_this_mode = 0;
490                     switch(g_disp_mode[id].Format)
491                     {
492                     case D3DFMT_R8G8B8  : bpp_this_mode = 32; break;
493                     case D3DFMT_A8R8G8B8: bpp_this_mode = 32; break;
494                     case D3DFMT_X8R8G8B8: bpp_this_mode = 32; break;
495                     case D3DFMT_R5G6B5  : bpp_this_mode = 16; break;
496                     case D3DFMT_X1R5G5B5: bpp_this_mode = 16; break;
497                     case D3DFMT_A1R5G5B5: bpp_this_mode = 16; break;
498                     case D3DFMT_A4R4G4B4: bpp_this_mode = 16; break;
499                     case D3DFMT_R3G3B2  : bpp_this_mode =  8; break;
500                     case D3DFMT_A8R3G3B2: bpp_this_mode = 16; break;
501                     case D3DFMT_X4R4G4B4: bpp_this_mode = 16; break;
502                     }
503 
504                     bool bMatch = true;
505 
506                     if (rep < 4)
507                     {
508                         if (desired_mode.Width != g_disp_mode[id].Width)
509                             bMatch = false;
510                         if (desired_mode.Height != g_disp_mode[id].Height)
511                             bMatch = false;
512                     }
513                     else if (rep < 8)
514                     {
515                         if (DEFAULT_FULLSCREEN_WIDTH != g_disp_mode[id].Width)
516                             bMatch = false;
517                         if (DEFAULT_FULLSCREEN_HEIGHT != g_disp_mode[id].Height)
518                             bMatch = false;
519                     }
520 
521                     if (((rep/2)%2)==0)
522                     {
523                         if (pass==0 && desired_mode.Format != g_disp_mode[id].Format)
524                             bMatch = false;
525                         else if (pass==1 && bpp_desired != bpp_this_mode)
526                             bMatch = false;
527                     }
528 
529                     if (((rep%2)==0) && desired_mode.RefreshRate!=g_disp_mode[id].RefreshRate)
530                     {
531                         bMatch = false;
532                     }
533 
534                     if (bMatch)
535                     {
536                         SendMessage( hwnd_listbox, CB_SETCURSEL, i, 0);
537                         found = 1;
538                     }
539                 }
540             }
541         }
542 
543         // if no match could be found, select #0.
544         if (!found)
545             SendMessage( hwnd_listbox, CB_SETCURSEL, 0, 0);
546     }
547 
548     UpdateDispModeMultiSampling(0);
549 }
550 
UpdateDispModeMultiSampling(int screenmode)551 void CPluginShell::UpdateDispModeMultiSampling(int screenmode)
552 {
553     int nSampleTypes = 0;
554 
555     HWND hwnd_listbox;
556     switch(screenmode)
557     {
558     case FULLSCREEN:      hwnd_listbox = GetDlgItem(g_subwnd, IDC_FSMS);  break;
559     case WINDOWED:        hwnd_listbox = GetDlgItem(g_subwnd, IDC_WMS);   break;
560     case DESKTOP:         hwnd_listbox = GetDlgItem(g_subwnd, IDC_DMSMS);  break;
561     }
562 
563     wchar_t str[256];
564     int i;
565 
566     if (!g_lpDX)
567         return;
568 
569     if ((screenmode == WINDOWED && !m_allow_page_tearing_w) ||
570         (screenmode == FULLSCREEN && m_fake_fullscreen_mode && !m_allow_page_tearing_fs) ||
571         (screenmode == DESKTOP && !m_allow_page_tearing_dm))
572     {
573         // page tearing not allowed -> disable multisampling!
574         SendMessage( hwnd_listbox, CB_RESETCONTENT, 0, 0);
575         SendMessageW( hwnd_listbox, CB_ADDSTRING, 0, (LPARAM)WASABI_API_LNGSTRINGW(IDS_DISABLED_PAGE_TEARING));
576         SendMessage( hwnd_listbox, CB_SETITEMDATA, 0, 0 );
577         SendMessage( hwnd_listbox, CB_SETCURSEL, 0, 0);
578         EnableWindow( hwnd_listbox, 0 );
579     }
580     else
581     {
582         EnableWindow( hwnd_listbox, 1 );
583 
584         // figure out which [fullscreen/windowed] adapter is currently selected:
585         int nAdapterOrdinal = GetCurrentlySelectedAdapter(screenmode);
586 
587         // figure out current format:
588         D3DFORMAT format = D3DFMT_UNKNOWN;
589         if ((screenmode == WINDOWED) ||
590             (screenmode == FULLSCREEN && m_fake_fullscreen_mode) ||
591             (screenmode == DESKTOP))
592         {
593             // ** get it from the current display mode
594             //    of the currently-selected [windowed/fake fullscreen] mode adapter **
595             D3DDISPLAYMODE dispmode;
596             if (g_lpDX->GetAdapterDisplayMode(nAdapterOrdinal, &dispmode) == D3D_OK)
597                 format = dispmode.Format;
598         }
599         else
600         {
601             // **get it from the currently-selected fullscreen display mode**
602             int n = SendMessage( GetDlgItem( g_subwnd, IDC_DISP_MODE ), CB_GETCURSEL, 0, 0);
603             if (n != CB_ERR)
604             {
605                 // since the combobox contents were sorted, we need to look up the original
606                 // index into g_disp_mode[]:
607                 n = SendMessage( GetDlgItem( g_subwnd, IDC_DISP_MODE ), CB_GETITEMDATA, n, 0);
608                 if (n != CB_ERR)
609                     format = g_disp_mode[n].Format;
610             }
611         }
612 
613         D3DMULTISAMPLE_TYPE check[16] = {
614             D3DMULTISAMPLE_NONE,
615             D3DMULTISAMPLE_2_SAMPLES ,
616             D3DMULTISAMPLE_3_SAMPLES ,
617             D3DMULTISAMPLE_4_SAMPLES ,
618             D3DMULTISAMPLE_5_SAMPLES ,
619             D3DMULTISAMPLE_6_SAMPLES ,
620             D3DMULTISAMPLE_7_SAMPLES ,
621             D3DMULTISAMPLE_8_SAMPLES ,
622             D3DMULTISAMPLE_9_SAMPLES ,
623             D3DMULTISAMPLE_10_SAMPLES,
624             D3DMULTISAMPLE_11_SAMPLES,
625             D3DMULTISAMPLE_12_SAMPLES,
626             D3DMULTISAMPLE_13_SAMPLES,
627             D3DMULTISAMPLE_14_SAMPLES,
628             D3DMULTISAMPLE_15_SAMPLES,
629             D3DMULTISAMPLE_16_SAMPLES,
630         };
631 
632         // clear the combo box
633         SendMessage( hwnd_listbox, CB_RESETCONTENT, 0, 0);
634 
635         // re-populate it:
636         for (i=0; i<16; i++)
637         {
638             if (i==0 || SUCCEEDED(g_lpDX->CheckDeviceMultiSampleType(nAdapterOrdinal, D3DDEVTYPE_HAL,
639                                                            format,
640                                                            (screenmode==FULLSCREEN) ? 0 : 1,//bWindowed,
641                                                            check[i], NULL)))
642             {
643                 // add to listbox
644                 if (i==0)
645                     WASABI_API_LNGSTRINGW_BUF(IDS_NONE, str, 256);
646                 else
647                     StringCbPrintfW(str, sizeof(str), L"%2dX", i+1);
648 
649                 SendMessage( hwnd_listbox, CB_ADDSTRING, nSampleTypes, (LPARAM)str);
650 
651                 // set the item data to the D3DMULTISAMPLE_TYPE value:
652                 SendMessage( hwnd_listbox, CB_SETITEMDATA, nSampleTypes, check[i] );
653 
654                 nSampleTypes++;
655             }
656         }
657 
658         // set prev. selection
659         D3DMULTISAMPLE_TYPE prev_seln;
660         switch(screenmode)
661         {
662         case FULLSCREEN:      prev_seln = m_multisample_fullscreen;      break;
663         case WINDOWED:        prev_seln = m_multisample_windowed;        break;
664         //case FAKE_FULLSCREEN: prev_seln = m_multisample_fake_fullscreen; break;
665         case DESKTOP:         prev_seln = m_multisample_desktop;         break;
666         }
667 
668         for (i=0; i<nSampleTypes; i++)
669         {
670             int id = SendMessage( hwnd_listbox, CB_GETITEMDATA, i, 0);
671             if (id==prev_seln)
672             {
673                 SendMessage( hwnd_listbox, CB_SETCURSEL, i, 0);
674                 return;
675             }
676         }
677 
678         SendMessage( hwnd_listbox, CB_SETCURSEL, 0, 0);
679     }
680 }
681 
UpdateMaxFps(int screenmode)682 void CPluginShell::UpdateMaxFps(int screenmode)
683 {
684     // initialize sleep combo boxes
685     HWND ctrl;
686     switch(screenmode)
687     {
688     case FULLSCREEN:      ctrl = GetDlgItem(g_subwnd, IDC_FS_MAXFPS ); break;
689     case WINDOWED:        ctrl = GetDlgItem(g_subwnd, IDC_W_MAXFPS  ); break;
690     //case FAKE_FULLSCREEN: ctrl = GetDlgItem(g_subwnd, IDC_FFS_MAXFPS); break;
691     case DESKTOP:         ctrl = GetDlgItem(g_subwnd, IDC_DMS_MAXFPS); break;
692     }
693 
694     SendMessage( ctrl, CB_RESETCONTENT, 0, 0);
695     for (int j=0; j<=MAX_MAX_FPS; j++)
696     {
697         wchar_t buf[256];
698         if (j==0)
699 			WASABI_API_LNGSTRINGW_BUF(IDS_UNLIMITED, buf, 256);
700         else
701 			swprintf(buf, WASABI_API_LNGSTRINGW(IDS_X_FRAME_SEC), (j<MAX_MAX_FPS)?(MAX_MAX_FPS+1-j):(MAX_MAX_FPS+1-j));
702 
703         SendMessageW( ctrl, CB_ADDSTRING, j, (LPARAM)buf);
704     }
705 
706     // set prev. selection
707     int max_fps;
708     switch(screenmode)
709     {
710     case FULLSCREEN:      max_fps = m_max_fps_fs; break;
711     case WINDOWED:        max_fps = m_max_fps_w;  break;
712     //case FAKE_FULLSCREEN: max_fps = m_max_fps_fake_fs; break;
713     case DESKTOP:         max_fps = m_max_fps_dm; break;
714     }
715     if (max_fps == 0)
716         SendMessage(ctrl, CB_SETCURSEL, 0,  0);
717     else
718         SendMessage(ctrl, CB_SETCURSEL, MAX_MAX_FPS-max_fps+1,  0);
719 }
720 
GetCurrentlySelectedAdapter(int screenmode)721 int CPluginShell::GetCurrentlySelectedAdapter(int screenmode)
722 {
723     // returns the ordinal adapter #.
724     HWND ctrl;
725     switch(screenmode)
726     {
727     case FULLSCREEN:      ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_FS ); break;
728     case WINDOWED:        ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_W  ); break;
729     //case FAKE_FULLSCREEN: ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_FFS); break;
730     case DESKTOP:         ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_DMS); break;
731     }
732 
733     int n = SendMessage(ctrl, CB_GETCURSEL, 0, 0);
734     //if (n != CB_ERR)
735     //    n = SendMessage(ctrl, CB_GETITEMDATA, n, 0);
736     if (n != CB_ERR)
737         return n;
738     else
739         return D3DADAPTER_DEFAULT;
740 }
741 
SaveDisplayMode()742 void CPluginShell::SaveDisplayMode()
743 {
744     //if (m_fake_fullscreen_mode)
745     //    return;
746 
747     // read fullscreen display mode
748     int n = SendMessage( GetDlgItem( g_subwnd, IDC_DISP_MODE ), CB_GETCURSEL, 0, 0);
749     if (n != CB_ERR)
750     {
751         // since the combobox contents were sorted, we need to look up the original
752         // index into g_disp_mode[]:
753         n = SendMessage( GetDlgItem( g_subwnd, IDC_DISP_MODE ), CB_GETITEMDATA, n, 0);
754         if (n != CB_ERR)
755             m_disp_mode_fs = g_disp_mode[n];
756     }
757 }
758 
SaveMultiSamp(int screenmode)759 void CPluginShell::SaveMultiSamp(int screenmode)
760 {
761     HWND ctrl;
762     switch(screenmode)
763     {
764     case FULLSCREEN:      ctrl = GetDlgItem(g_subwnd, IDC_FSMS);  break;
765     case WINDOWED:        ctrl = GetDlgItem(g_subwnd, IDC_WMS);   break;
766     //case FAKE_FULLSCREEN: ctrl = GetDlgItem(g_subwnd, IDC_FFSMS); break;
767     case DESKTOP:         ctrl = GetDlgItem(g_subwnd, IDC_DMSMS); break;
768     }
769 
770     // if page tearing is disabled, then multisampling must be disabled,
771     // so ignore multisample selection
772     if (g_subwnd && g_nTab==0)
773     {
774         if (screenmode == WINDOWED && !m_allow_page_tearing_w)
775             return;
776         if (screenmode == DESKTOP && !m_allow_page_tearing_dm)
777             return;
778         if (screenmode == FULLSCREEN && m_fake_fullscreen_mode && !m_allow_page_tearing_fs)
779             return;
780     }
781 
782     // read windowed & fullscreen multisampling settings:
783     int n = SendMessage(ctrl , CB_GETCURSEL, 0, 0);
784     if (n != CB_ERR)
785     {
786         n = SendMessage( ctrl, CB_GETITEMDATA, n, 0);
787         if (n != CB_ERR)
788         {
789             switch(screenmode)
790             {
791             case FULLSCREEN:      m_multisample_fullscreen      = (D3DMULTISAMPLE_TYPE)n; break;
792             case WINDOWED:        m_multisample_windowed        = (D3DMULTISAMPLE_TYPE)n; break;
793             //case FAKE_FULLSCREEN: m_multisample_fake_fullscreen = (D3DMULTISAMPLE_TYPE)n; break;
794             case DESKTOP:         m_multisample_desktop         = (D3DMULTISAMPLE_TYPE)n; break;
795             }
796         }
797     }
798 }
799 
SaveMaxFps(int screenmode)800 void CPluginShell::SaveMaxFps(int screenmode)
801 {
802     HWND ctrl;
803     switch(screenmode)
804     {
805     case FULLSCREEN:      ctrl = GetDlgItem(g_subwnd, IDC_FS_MAXFPS);  break;
806     case WINDOWED:        ctrl = GetDlgItem(g_subwnd, IDC_W_MAXFPS);   break;
807     //case FAKE_FULLSCREEN: ctrl = GetDlgItem(g_subwnd, IDC_FFS_MAXFPS); break;
808     case DESKTOP:         ctrl = GetDlgItem(g_subwnd, IDC_DMS_MAXFPS); break;
809     }
810 
811     // read max fps settings
812     int n = SendMessage(ctrl, CB_GETCURSEL, 0, 0);
813     if (n != CB_ERR)
814     {
815         if (n > 0)
816             n = MAX_MAX_FPS+1 - n;
817 
818         switch(screenmode)
819         {
820         case FULLSCREEN:      m_max_fps_fs = n; break;
821         case WINDOWED:        m_max_fps_w  = n; break;
822         //case FAKE_FULLSCREEN: m_max_fps_fake_fs = n; break;
823         case DESKTOP:         m_max_fps_dm = n; break;
824         }
825     }
826 }
827 
SaveAdapter(int screenmode)828 void CPluginShell::SaveAdapter(int screenmode)
829 {
830     HWND ctrl;
831     switch(screenmode)
832     {
833     case FULLSCREEN:      ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_FS);  break;
834     case WINDOWED:        ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_W);   break;
835     //case FAKE_FULLSCREEN: ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_FFS); break;
836     case DESKTOP:         ctrl = GetDlgItem(g_subwnd, IDC_ADAPTER_DMS); break;
837     }
838 
839     // save windowed/fullscreen adapter
840     int n = SendMessage( ctrl, CB_GETCURSEL, 0, 0);
841     if (n != CB_ERR)
842     {
843         switch(screenmode)
844         {
845         case FULLSCREEN:
846             m_adapter_guid_fullscreen      = g_disp_adapter_fs[n].DeviceIdentifier;
847             StringCbCopy(m_adapter_devicename_fullscreen, sizeof(m_adapter_devicename_fullscreen), g_disp_adapter_fs[n].DeviceName);
848             //strcpy(m_adapter_desc_fullscreen, g_disp_adapter_fs[n].Description);
849             break;
850         case WINDOWED:
851             m_adapter_guid_windowed        = g_disp_adapter_w[n].DeviceIdentifier;
852             StringCbCopy(m_adapter_devicename_windowed, sizeof(m_adapter_devicename_windowed), g_disp_adapter_fs[n].DeviceName);
853             //strcpy(m_adapter_desc_windowed, g_disp_adapter_fs[n].Description);
854             break;
855         //case FAKE_FULLSCREEN:
856             //m_adapter_guid_fake_fullscreen = g_disp_adapter_w[n].DeviceIdentifier;
857             //strcpy(m_adapter_desc_fake_fullscreen, g_disp_adapter_fs[n].Description);
858             //break; // [sic]
859         case DESKTOP:
860             m_adapter_guid_desktop         = g_disp_adapter_dm[n].DeviceIdentifier;
861             StringCbCopy(m_adapter_devicename_desktop, sizeof(m_adapter_devicename_desktop), g_disp_adapter_fs[n].DeviceName);
862             //strcpy(m_adapter_desc_desktop, g_disp_adapter_fs[n].Description);
863             break;
864         }
865     }
866 }
867 
868 /*
869 BOOL CALLBACK GenericTabCtrlProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
870 {
871     return 0;
872 }
873 */
874 
875 // OnTabChanged - processes the TCN_SELCHANGE notification.
OnTabChanged(int nNewTab)876 void CPluginShell::OnTabChanged(int nNewTab)
877 {
878     if (g_subwnd)
879     {
880         DestroyWindow(g_subwnd);
881         g_subwnd = NULL;
882     }
883 
884     g_nTab = nNewTab;
885 
886     if (g_nTab >= 0 && g_nTab < MAX_PROPERTY_PAGES)
887     {
888 		HWND h = WASABI_API_CREATEDIALOGPARAMW(g_proppage_id[g_nTab], g_config_hwnd, this->TabCtrlProc, (LPARAM)this);
889 		// NOTE: CreateDialogParam will call TabCtrlProc with WM_INITDIALOG,
890         // which is where 'g_subwnd' will get set.
891 
892         // do this here to ensure that the current prefs page is correctly themed
893         if(!SendMessage(this->m_hWndWinamp,WM_WA_IPC,IPC_ISWINTHEMEPRESENT,IPC_USE_UXTHEME_FUNC))
894         {
895             SendMessage(this->m_hWndWinamp,WM_WA_IPC,(WPARAM)h,IPC_USE_UXTHEME_FUNC);
896         }
897     }
898 }
899 
TabCtrlProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)900 INT_PTR CALLBACK CPluginShell::TabCtrlProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
901 {
902     if (msg==WM_INITDIALOG && lParam > 0 && GetWindowLongPtr(hwnd,GWLP_USERDATA)==0)
903         SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
904 
905     CPluginShell* p = (CPluginShell*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
906 
907     if (p && g_nTab >= 0 && g_nTab < MAX_PROPERTY_PAGES)
908     {
909         if (msg==WM_INITDIALOG)
910             g_subwnd = hwnd;
911 
912         if (g_nTab==0)
913             p->PluginShellConfigTab1Proc(hwnd, msg, wParam, lParam);
914         p->MyConfigTabProc(g_nTab+1, hwnd, msg, wParam, lParam);
915 
916         if (msg==WM_INITDIALOG)
917         {
918             // once it has been initialized, reposition the subdialog:
919             RECT r;
920 		    GetWindowRect(GetDlgItem(g_config_hwnd,IDC_RECT),&r);
921 		    ScreenToClient(g_config_hwnd,(LPPOINT)&r);
922 		    SetWindowPos(g_subwnd,0,r.left,r.top,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
923 	        ShowWindow(g_subwnd,SW_SHOWNA);
924         }
925     }
926 
927 	const int controls[] =
928 	{
929 		IDC_BRIGHT_SLIDER,
930 		IDC_HARDCUT_LOUDNESS,
931 	};
932 	if (FALSE != WASABI_API_APP->DirectMouseWheel_ProcessDialogMessage(hwnd, msg, wParam, lParam, controls, ARRAYSIZE(controls)))
933 	{
934 		return TRUE;
935 	}
936 
937     return FALSE;
938 }
939 
PluginShellConfigTab1Proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)940 BOOL CPluginShell::PluginShellConfigTab1Proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
941 {
942     #ifdef _DEBUG
943         OutputDebugMessage("   Tab1Proc: ", hwnd, msg, wParam, lParam);
944     #endif
945 
946     switch (msg)
947     {
948     case WM_INITDIALOG:
949         {
950             // pre-checks
951             if (m_start_fullscreen && m_start_desktop)
952                 m_start_desktop = 0;
953             if (!mod1.hwndParent || SendMessage(mod1.hwndParent,WM_WA_IPC,0,0) < 0x2900)
954             {
955                 m_skin = 0;
956                 EnableWindow(GetDlgItem(hwnd,IDC_CB_SKIN), 0);
957                 char buf[256];
958                 buf[0] = 0;
959                 GetWindowText(GetDlgItem(hwnd,IDC_CB_SKIN), buf, 255);
960                 StringCbCat(buf, sizeof(buf), " 2.90+");
961                 SetWindowText(GetDlgItem(hwnd,IDC_CB_SKIN), buf);
962             }
963 
964             // set checkboxes
965             CheckDlgButton(hwnd, IDC_CB_FS,  m_start_fullscreen);
966             CheckDlgButton(hwnd, IDC_CB_DMS,  m_start_desktop);
967             CheckDlgButton(hwnd, IDC_CB_FAKE, m_fake_fullscreen_mode);
968             CheckDlgButton(hwnd, IDC_CB_PRESS_F1_MSG, m_show_press_f1_msg);
969             CheckDlgButton(hwnd, IDC_CB_WPT, m_allow_page_tearing_w);
970             CheckDlgButton(hwnd, IDC_CB_FSPT, m_allow_page_tearing_fs);
971             CheckDlgButton(hwnd, IDC_CB_DMSPT, m_allow_page_tearing_dm);
972             CheckDlgButton(hwnd, IDC_CB_MIN, m_minimize_winamp);
973             CheckDlgButton(hwnd, IDC_CB_SAVE_CPU, m_save_cpu);
974             CheckDlgButton(hwnd, IDC_CB_SKIN, m_skin);
975 			CheckDlgButton(hwnd, IDC_CB_FIXSLOWTEXT, m_fix_slow_text);
976             CheckDlgButton(hwnd, IDC_CB_VJMODE, m_vj_mode);
977 
978             // Enumerate available adapters.
979             UpdateAdapters(0);    // fullscreen
980               //-calls UpdateFSAdapterDispModes()
981               //-which then calls UpdateDispModeMultiSampling(0).
982             UpdateAdapters(1);    // windowed
983               //-skips UpdateFSAdapterDispModes() (not necessary for windowed mode)
984               //-then calls UpdateDispModeMultiSampling(1).
985             UpdateAdapters(3);    // desktop
986               //-skips UpdateFSAdapterDispModes() (not necessary for fake fullscreen mode)
987               //-then calls UpdateDispModeMultiSampling(2).
988             UpdateMaxFps(0);
989             UpdateMaxFps(1);
990             UpdateMaxFps(3); // desktop
991 
992             // disable a few things if fake fullscreen mode enabled:
993             EnableWindow(GetDlgItem(hwnd, IDC_DISP_MODE), !m_fake_fullscreen_mode);
994             //EnableWindow(GetDlgItem(hwnd, IDC_FSMS), !m_fake_fullscreen_mode);
995         }
996         break;
997 
998     case WM_DESTROY:
999         {
1000             // read checkboxes
1001             m_start_fullscreen     = DlgItemIsChecked(hwnd, IDC_CB_FS   );
1002             m_start_desktop        = DlgItemIsChecked(hwnd, IDC_CB_DMS  );
1003             m_fake_fullscreen_mode = DlgItemIsChecked(hwnd, IDC_CB_FAKE );
1004             m_show_press_f1_msg    = DlgItemIsChecked(hwnd, IDC_CB_PRESS_F1_MSG);
1005             m_allow_page_tearing_w = DlgItemIsChecked(hwnd, IDC_CB_WPT  );
1006             m_allow_page_tearing_fs= DlgItemIsChecked(hwnd, IDC_CB_FSPT  );
1007             m_allow_page_tearing_dm= DlgItemIsChecked(hwnd, IDC_CB_DMSPT);
1008             m_minimize_winamp      = DlgItemIsChecked(hwnd, IDC_CB_MIN  );
1009             m_save_cpu             = DlgItemIsChecked(hwnd, IDC_CB_SAVE_CPU );
1010             m_fix_slow_text        = DlgItemIsChecked(hwnd, IDC_CB_FIXSLOWTEXT);
1011             m_vj_mode              = DlgItemIsChecked(hwnd, IDC_CB_VJMODE);
1012 
1013             if (mod1.hwndParent && SendMessage(mod1.hwndParent,WM_WA_IPC,0,0) >= 0x2900)
1014                 m_skin             = DlgItemIsChecked(hwnd, IDC_CB_SKIN );
1015 
1016             // read all 3 adapters
1017             SaveAdapter(0);
1018             SaveAdapter(1);
1019             SaveAdapter(3);
1020 
1021             // read fullscreen display mode
1022             SaveDisplayMode();
1023 
1024             // read all 3 multisampling settings:
1025             SaveMultiSamp(0);
1026             SaveMultiSamp(1);
1027             SaveMultiSamp(3);
1028 
1029             // read all 3 max fps settings
1030             SaveMaxFps(0);
1031             SaveMaxFps(1);
1032             SaveMaxFps(3);
1033         }
1034         break;
1035 
1036     case WM_COMMAND:
1037         if (!g_ignore_clicks)
1038         {
1039             int id = LOWORD(wParam);
1040             g_ignore_clicks = 1;
1041             switch(id)
1042             {
1043 			case ID_FONTS:
1044                 WASABI_API_DIALOGBOXPARAMW(IDD_FONTDIALOG, hwnd, FontDialogProc, (LPARAM)this);
1045                 break;
1046 
1047 			case ID_DM_MORE:
1048                 WASABI_API_DIALOGBOXPARAMW(IDD_DESKTOPMODE, hwnd, DesktopOptionsDialogProc, (LPARAM)this);
1049                 break;
1050 
1051 			case ID_DUALHEAD:
1052                 WASABI_API_DIALOGBOXPARAMW(IDD_DUALHEAD, hwnd, DualheadDialogProc, (LPARAM)this);
1053                 break;
1054 
1055             case IDC_ADAPTER_FS:
1056                 SaveDisplayMode();
1057                 SaveMultiSamp(FULLSCREEN);
1058                 SaveAdapter(0);
1059                 UpdateFSAdapterDispModes();
1060                 break;
1061 
1062             case IDC_ADAPTER_W:
1063                 SaveMultiSamp(WINDOWED);
1064                 UpdateDispModeMultiSampling(WINDOWED);
1065                 break;
1066 
1067                 /*
1068             case IDC_ADAPTER_FFS:
1069                 SaveMultiSamp(FAKE_FULLSCREEN);
1070                 UpdateDispModeMultiSampling(FAKE_FULLSCREEN);
1071                 break;
1072                 */
1073 
1074             case IDC_ADAPTER_DMS:
1075                 SaveMultiSamp(DESKTOP);
1076                 UpdateDispModeMultiSampling(DESKTOP);
1077                 break;
1078 
1079             case IDC_DISP_MODE:
1080                 SaveMultiSamp(FULLSCREEN);
1081                 UpdateDispModeMultiSampling(FULLSCREEN);
1082                 break;
1083 
1084             case IDC_CB_WPT:
1085                 SaveMultiSamp(WINDOWED);
1086                 m_allow_page_tearing_w = DlgItemIsChecked(hwnd, IDC_CB_WPT);
1087                 UpdateDispModeMultiSampling(WINDOWED);
1088                 break;
1089 
1090             case IDC_CB_FSPT:
1091                 SaveMultiSamp(FULLSCREEN);
1092                 m_allow_page_tearing_fs = DlgItemIsChecked(hwnd, IDC_CB_FSPT);
1093                 UpdateDispModeMultiSampling(FULLSCREEN);
1094                 break;
1095 
1096             case IDC_CB_DMSPT:
1097                 SaveMultiSamp(DESKTOP);
1098                 m_allow_page_tearing_dm = DlgItemIsChecked(hwnd, IDC_CB_DMSPT);
1099                 UpdateDispModeMultiSampling(DESKTOP);
1100                 break;
1101 
1102             case IDC_CB_FS:
1103                 m_start_fullscreen     = DlgItemIsChecked(hwnd, IDC_CB_FS   );
1104                 if (m_start_fullscreen && m_start_desktop)
1105                 {
1106                     m_start_desktop = 0;
1107                     CheckDlgButton(hwnd, IDC_CB_DMS,  m_start_desktop);
1108                 }
1109                 break;
1110 
1111             case IDC_CB_DMS:
1112                 m_start_desktop        = DlgItemIsChecked(hwnd, IDC_CB_DMS  );
1113                 if (m_start_fullscreen && m_start_desktop)
1114                 {
1115                     m_start_fullscreen = 0;
1116                     CheckDlgButton(hwnd, IDC_CB_FS,  m_start_fullscreen);
1117                 }
1118                 break;
1119 
1120             case IDC_CB_FAKE:
1121                 SaveMultiSamp(FULLSCREEN);
1122                 m_fake_fullscreen_mode = DlgItemIsChecked(hwnd, IDC_CB_FAKE );
1123                 EnableWindow(GetDlgItem(hwnd, IDC_DISP_MODE), !m_fake_fullscreen_mode);
1124                 CheckDlgButton(hwnd, IDC_CB_FSPT, m_fake_fullscreen_mode ? m_allow_page_tearing_fs : 0);
1125                 EnableWindow(GetDlgItem(hwnd, IDC_CB_FSPT), m_fake_fullscreen_mode ? 1 : 0);
1126                 UpdateDispModeMultiSampling(FULLSCREEN);
1127                 break;
1128 
1129                 /*
1130             case IDC_CB_FFSPT:
1131                 SaveMultiSamp(FAKE_FULLSCREEN);
1132                 m_allow_page_tearing_fake_fs = DlgItemIsChecked(hwnd, IDC_CB_FFSPT);
1133                 UpdateDispModeMultiSampling(FAKE_FULLSCREEN);
1134                 break;
1135                 */
1136             }
1137             g_ignore_clicks = 0;
1138         }
1139         break;  // case WM_COMMAND
1140 
1141     case WM_HELP:
1142         if (lParam)
1143         {
1144             HELPINFO *ph = (HELPINFO*)lParam;
1145             wchar_t title[1024];
1146             wchar_t buf[2048];
1147             wchar_t ctrl_name[1024];
1148             GetWindowTextW(GetDlgItem(hwnd, ph->iCtrlId), ctrl_name, sizeof(ctrl_name)/sizeof(*ctrl_name));
1149             RemoveSingleAmpersands(ctrl_name);
1150             buf[0] = 0;
1151 
1152             switch(ph->iCtrlId)
1153             {
1154             case ID_FONTS:
1155                 StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_BUTTON), ctrl_name);
1156                 WASABI_API_LNGSTRINGW_BUF(IDS_FONTS_HELP, buf, 2048);
1157                 break;
1158 
1159             case ID_DUALHEAD:
1160 				StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_BUTTON), ctrl_name);
1161                 WASABI_API_LNGSTRINGW_BUF(IDS_DUAL_HEAD_HELP, buf, 2048);
1162                 break;
1163 
1164             case IDC_W_MULTISAMPLING_CAPTION:
1165             case IDC_FS_MULTISAMPLING_CAPTION:
1166             case IDC_DMS_MULTISAMPLING_CAPTION:
1167             //case IDC_FFS_MULTISAMPLING_CAPTION:
1168             case IDC_WMS:
1169             case IDC_FSMS:
1170             case IDC_DMSMS:
1171             //case IDC_FFSMS:
1172                 WASABI_API_LNGSTRINGW_BUF(IDS_MULTI_SAMPLING, title, 1024);
1173                 WASABI_API_LNGSTRINGW_BUF(IDS_MULTI_SAMPLING_HELP, buf, 2048);
1174                 break;
1175 
1176             case IDC_W_MAXFPS:
1177             case IDC_FS_MAXFPS:
1178             case IDC_DMS_MAXFPS:
1179             //case IDC_FFS_MAXFPS:
1180             case IDC_W_MAXFPS_CAPTION:
1181             case IDC_FS_MAXFPS_CAPTION:
1182             case IDC_DMS_MAXFPS_CAPTION:
1183             //case IDC_FFS_MAXFPS_CAPTION:
1184                 WASABI_API_LNGSTRINGW_BUF(IDS_MAX_FRAMERATE, title, 1024);
1185 				WASABI_API_LNGSTRINGW_BUF(IDS_MAX_FRAMERATE_HELP, buf, 2048);
1186                 break;
1187 
1188             case IDC_CB_FAKE:
1189                 WASABI_API_LNGSTRINGW_BUF(IDS_FAKE_FULLSCREEN, title, 1024);
1190 				WASABI_API_LNGSTRINGW_BUF(IDS_FAKE_FULLSCREEN_HELP, buf, 2048);
1191                 break;
1192 
1193             case IDC_ADAPTER_FS:
1194             case IDC_FS_ADAPTER_CAPTION:
1195                 WASABI_API_LNGSTRINGW_BUF(IDS_FULLSCREEN_ADAPTER, title, 1024);
1196 				WASABI_API_LNGSTRINGW_BUF(IDS_FULLSCREEN_ADAPTER_HELP, buf, 2048);
1197                 break;
1198 
1199             case IDC_ADAPTER_W:
1200             case IDC_W_ADAPTER_CAPTION:
1201 				WASABI_API_LNGSTRINGW_BUF(IDS_WINDOWED_ADPATER, title, 1024);
1202 				WASABI_API_LNGSTRINGW_BUF(IDS_WINDOWED_ADPATER_HELP, buf, 2048);
1203                 break;
1204 
1205             case IDC_ADAPTER_DMS:
1206             case IDC_DMS_ADAPTER_CAPTION:
1207 				WASABI_API_LNGSTRINGW_BUF(IDS_DESKTOP_ADAPTER, title, 1024);
1208 				WASABI_API_LNGSTRINGW_BUF(IDS_DESKTOP_ADAPTER_HELP, buf, 2048);
1209                 break;
1210 
1211             case IDC_DISP_MODE:
1212             case IDC_DISP_MODE_CAPTION:
1213                 WASABI_API_LNGSTRINGW_BUF(IDS_FS_DISPLAY_MODE, title, 1024);
1214 				WASABI_API_LNGSTRINGW_BUF(IDS_FS_DISPLAY_MODE_HELP, buf, 2048);
1215                 break;
1216 
1217             case IDC_CB_WPT:
1218             case IDC_CB_FSPT:
1219             case IDC_CB_DMSPT:
1220             //case IDC_CB_FFSPT:
1221                 StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_CHECKBOX), ctrl_name);
1222 				WASABI_API_LNGSTRINGW_BUF(IDS_HELP_ON_X_CHECKBOX_HELP, buf, 2048);
1223                 break;
1224 
1225             case IDC_CB_FS:
1226                 StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_CHECKBOX), ctrl_name);
1227                 WASABI_API_LNGSTRINGW_BUF(IDS_FORCE_INTO_FS_MODE_HELP, buf, 2048);
1228                 break;
1229 
1230             case IDC_CB_DMS:
1231 				StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_CHECKBOX), ctrl_name);
1232                 WASABI_API_LNGSTRINGW_BUF(IDS_FORCE_INTO_DESKTOP_MODE_HELP, buf, 2048);
1233                 break;
1234 
1235             case IDC_CB_PRESS_F1_MSG:
1236                 WASABI_API_LNGSTRINGW_BUF(IDS_HELP_ON_F1, title, 1024);
1237 				WASABI_API_LNGSTRINGW_BUF(IDS_HELP_ON_F1_HELP, buf, 2048);
1238                 break;
1239 
1240             case IDC_CB_SKIN:
1241 				StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_CHECKBOX), ctrl_name);
1242 				WASABI_API_LNGSTRINGW_BUF(IDS_CB_SKIN_HELP, buf, 2048);
1243                 break;
1244 
1245             case IDC_CB_SAVE_CPU:
1246                 WASABI_API_LNGSTRINGW_BUF(IDS_SAVE_CPU_CHECKBOX, title, 1024);
1247 				WASABI_API_LNGSTRINGW_BUF(IDS_SAVE_CPU_CHECKBOX_HELP, buf, 2048);
1248                 break;
1249 
1250             case IDC_CB_MIN:
1251                 WASABI_API_LNGSTRINGW_BUF(IDS_HELP_MINIMIZE_WINAMP, title, 1024);
1252 				WASABI_API_LNGSTRINGW_BUF(IDS_HELP_MINIMIZE_WINAMP_HELP, buf, 2048);
1253                 break;
1254 
1255             case IDC_CB_FIXSLOWTEXT:
1256                 WASABI_API_LNGSTRINGW_BUF(IDS_TRY_TO_FIX_SLOW_TEXT, title, 1024);
1257 				WASABI_API_LNGSTRINGW_BUF(IDS_TRY_TO_FIX_SLOW_TEXT_HELP, buf, 2048);
1258                 break;
1259 
1260             case IDC_CB_VJMODE:
1261                 WASABI_API_LNGSTRINGW_BUF(IDS_VJ_MODE, title, 1024);
1262 				WASABI_API_LNGSTRINGW_BUF(IDS_VJ_MODE_HELP, buf, 2048);
1263                 break;
1264 
1265             case IDC_DMS_LABEL:
1266                 StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X), ctrl_name);
1267 				WASABI_API_LNGSTRINGW_BUF(IDS_DMS_LABEL_HELP, buf, 2048);
1268                 break;
1269 
1270             case IDC_FS_LABEL:
1271                 StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X), ctrl_name);
1272 				WASABI_API_LNGSTRINGW_BUF(IDS_FS_LABEL_HELP, buf, 2048);
1273                 break;
1274 
1275             case IDC_W_LABEL:
1276                 StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X), ctrl_name);
1277 				WASABI_API_LNGSTRINGW_BUF(IDS_W_LABEL_HELP, buf, 2048);
1278                 break;
1279 
1280             case ID_DM_MORE:
1281                 StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X), ctrl_name);
1282 				WASABI_API_LNGSTRINGW_BUF(IDS_DM_MORE_HELP, buf, 2048);
1283                 break;
1284             }
1285 
1286             if (buf[0])
1287                 MessageBoxW(hwnd, buf, title, MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
1288 
1289         }
1290         break;  // case WM_HELP
1291     }
1292 
1293     return 0;
1294 }
1295 
ConfigDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)1296 BOOL CALLBACK CPluginShell::ConfigDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
1297 {
1298     if (msg==WM_INITDIALOG && lParam > 0 && GetWindowLongPtr(hwnd,GWLP_USERDATA)==0)
1299 			SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
1300 
1301     CPluginShell* p = (CPluginShell*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
1302 
1303     if (p)
1304         return p->PluginShellConfigDialogProc(hwnd, msg, wParam, lParam);
1305     else
1306         return FALSE;
1307 }
1308 
PluginShellConfigDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)1309 BOOL CPluginShell::PluginShellConfigDialogProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
1310 {
1311     #ifdef _DEBUG
1312         OutputDebugMessage("CfgDlgProc:  ", hwnd, msg, wParam, lParam);
1313     #endif
1314 
1315     switch (msg)
1316     {
1317     case WM_DESTROY:
1318         EndConfig();
1319         return 0;
1320 
1321     case WM_INITDIALOG:
1322         {
1323             // Initialize all config panel global variables:
1324             if (!InitConfig(hwnd))
1325             {
1326 				wchar_t title[64];
1327                 MessageBoxW(hwnd, WASABI_API_LNGSTRINGW(IDS_INITCONFIG_FAILED),
1328 						    WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
1329 						    MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
1330                 EndConfig();
1331                 int id=LOWORD(wParam);
1332                 EndDialog(hwnd,id);
1333                 return false;
1334             }
1335 
1336             // set window caption
1337             SetWindowText( hwnd, WINDOWCAPTION );
1338 
1339             // Test for DirectX 9 + start it
1340             // note: if you don't call LoadLibrary here, and you're on a system
1341             //       where DX9 is missing, Direct3DCreate9() might crash; so call it.
1342             int d3d9_already_loaded = (GetModuleHandle("d3d9.dll") != NULL) ? 1 : 0;
1343             if (!d3d9_already_loaded)
1344                 g_hmod_d3d9 = LoadLibrary("d3d9.dll");
1345 
1346             if ( (!d3d9_already_loaded && !g_hmod_d3d9) ||
1347                  !(g_lpDX = Direct3DCreate9(D3D_SDK_VERSION))
1348                )
1349             {
1350                 MissingDirectX(hwnd);
1351 
1352                 EndConfig();
1353                 int id=LOWORD(wParam);
1354                 EndDialog(hwnd,id);
1355                 return false;
1356             }
1357 
1358 				    if (!g_hmod_d3dx9)
1359 					    g_hmod_d3dx9 = FindD3DX9(GetWinampWindow());
1360 
1361 						if ((!g_hmod_d3dx9))
1362 						{
1363 	 		        MissingDirectX(hwnd);
1364               EndConfig();
1365               int id=LOWORD(wParam);
1366               EndDialog(hwnd,id);
1367               return false;
1368 						}
1369 
1370             // enable the 'view website' button only if plugin author has #defined a URL (in defines.h):
1371             #ifndef PLUGIN_WEB_URL
1372                 ShowWindow(GetDlgItem(hwnd, ID_WEB), SW_HIDE);
1373             #else
1374                 if (wcslen(PLUGIN_WEB_URL)==0)
1375                     ShowWindow(GetDlgItem(hwnd, ID_WEB), SW_HIDE);
1376             #endif
1377 
1378             // enable the 'view docs' button only if plugin author has #defined a filename (in defines.h):
1379             #ifndef DOCFILE
1380                 ShowWindow(GetDlgItem(hwnd, ID_DOCS), SW_HIDE);
1381             #else
1382                 if (wcslen(DOCFILE)==0)
1383                     ShowWindow(GetDlgItem(hwnd, ID_DOCS), SW_HIDE);
1384             #endif
1385 
1386             // set contents of IDC_SZ_ABOUT
1387 			wchar_t about[256];
1388 			StringCchPrintfW(about, 256, WASABI_API_LNGSTRINGW(IDS_ABOUT_STRING), LONGNAMEW, AUTHOR_NAME, COPYRIGHT);
1389             SetDlgItemTextW(hwnd, IDC_SZ_ABOUT, about);
1390 
1391             // initialize tab control:
1392             {
1393 				HWND tabWnd = GetDlgItem(hwnd,IDC_TABS);
1394                 // Add Tabs:
1395                 if (!AddButton(0, tabWnd, WASABI_API_LNGSTRINGW(IDS_CONFIG_PANEL_BUTTON_1)) ||
1396                     !AddButton(1, tabWnd, WASABI_API_LNGSTRINGW(IDS_CONFIG_PANEL_BUTTON_2)) ||
1397                     !AddButton(2, tabWnd, WASABI_API_LNGSTRINGW(IDS_CONFIG_PANEL_BUTTON_3)) ||
1398                     !AddButton(3, tabWnd, WASABI_API_LNGSTRINGW(IDS_CONFIG_PANEL_BUTTON_4)) ||
1399                     !AddButton(4, tabWnd, WASABI_API_LNGSTRINGW(IDS_CONFIG_PANEL_BUTTON_5)) ||
1400                     !AddButton(5, tabWnd, WASABI_API_LNGSTRINGW(IDS_CONFIG_PANEL_BUTTON_6)) ||
1401                     !AddButton(6, tabWnd, WASABI_API_LNGSTRINGW(IDS_CONFIG_PANEL_BUTTON_7)) ||
1402                     !AddButton(7, tabWnd, WASABI_API_LNGSTRINGW(IDS_CONFIG_PANEL_BUTTON_8)))
1403                 {
1404 					wchar_t title[64];
1405                     MessageBoxW(hwnd, WASABI_API_LNGSTRINGW(IDS_UNABLE_TO_LOAD_TABS),
1406 							    WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
1407 							    MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
1408                     EndConfig();
1409                     int id=LOWORD(wParam);
1410                     EndDialog(hwnd,id);
1411                     return false;
1412                 }
1413 
1414                 // Simulate selection of the first tab.
1415 				int last_tab = GetPrivateProfileIntW(L"settings",L"last_tab",0,m_szConfigIniFile);
1416 				TabCtrl_SetCurSel(tabWnd, last_tab);
1417                 OnTabChanged(last_tab);
1418             }
1419 
1420             g_ignore_clicks = 0;
1421 
1422             SetFocus(hwnd);
1423         }
1424         return 0;
1425 
1426     case WM_NOTIFY:
1427         if (!g_ignore_clicks)
1428         {
1429             LPNMHDR pnmh = (LPNMHDR)lParam;
1430             switch(pnmh->code)
1431             {
1432             case TCN_SELCHANGE:
1433                 OnTabChanged(TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_TABS)));
1434                 break;
1435             }
1436         }
1437         break;
1438 
1439     case WM_COMMAND:
1440         if (!g_ignore_clicks)
1441         {
1442             int id = LOWORD(wParam);
1443             switch(id)
1444             {
1445             case IDOK:
1446                 // kill current tab window, so that its settings get read
1447 				WritePrivateProfileIntW(TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_TABS)),L"last_tab",m_szConfigIniFile,L"settings");
1448                 OnTabChanged(-1);
1449 
1450                 // then save new config
1451                 WriteConfig();
1452 
1453                 EndDialog(hwnd,id);
1454                 return 0;
1455 
1456             case IDCANCEL:
1457 				WritePrivateProfileIntW(TabCtrl_GetCurSel(GetDlgItem(hwnd,IDC_TABS)),L"last_tab",m_szConfigIniFile,L"settings");
1458                 EndDialog(hwnd,id);
1459                 return 0;
1460 
1461             case ID_DOCS:
1462                 {
1463                     wchar_t szPath[512], szFile[512];
1464                     lstrcpyW(szPath, m_szPluginsDirPath);
1465                     lstrcpyW(szFile, szPath);
1466                     lstrcatW(szFile, DOCFILE);
1467 
1468 					intptr_t ret = myOpenURL(0,szFile);
1469                     if (ret <= 32)
1470                     {
1471                         wchar_t buf[1024];
1472                         switch(ret)
1473                         {
1474                         case SE_ERR_FNF:
1475                         case SE_ERR_PNF:
1476                             StringCbPrintfW(buf, sizeof(buf), WASABI_API_LNGSTRINGW(IDS_DOCUMENTATION_FILE_NOT_FOUND), szFile);
1477                             break;
1478                         case SE_ERR_ACCESSDENIED:
1479                         case SE_ERR_SHARE:
1480                             StringCbPrintfW(buf, sizeof(buf), WASABI_API_LNGSTRINGW(IDS_ACCESS_TO_DOCUMENTATION_FILE_DENIED), szFile);
1481                             break;
1482                         case SE_ERR_NOASSOC:
1483                             StringCbPrintfW(buf, sizeof(buf), WASABI_API_LNGSTRINGW(IDS_ACCESS_TO_DOCUMENTATION_FILE_FAILED_DUE_TO_NO_ASSOC), szFile);
1484                             break;
1485                         default:
1486                             StringCbPrintfW(buf, sizeof(buf), WASABI_API_LNGSTRINGW(IDS_ACCESS_TO_DOCUMENTATION_FILE_FAILED_CODE_X), szFile, ret);
1487                             break;
1488                         }
1489                         MessageBoxW(hwnd, buf, WASABI_API_LNGSTRINGW(IDS_ERROR_OPENING_DOCUMENTATION), MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
1490                     }
1491                 }
1492                 break;
1493 
1494             case ID_WEB:
1495                 {
1496                     intptr_t ret = myOpenURL(NULL, PLUGIN_WEB_URL);
1497                     if (ret <= 32)
1498                     {
1499                         wchar_t buf[1024];
1500                         switch(ret)
1501                         {
1502                         case SE_ERR_FNF:
1503                         case SE_ERR_PNF:
1504                             StringCbPrintfW(buf, sizeof(buf), WASABI_API_LNGSTRINGW(IDS_URL_COULD_NOT_OPEN), PLUGIN_WEB_URL);
1505                             break;
1506                         case SE_ERR_ACCESSDENIED:
1507                         case SE_ERR_SHARE:
1508                             StringCbPrintfW(buf, sizeof(buf), WASABI_API_LNGSTRINGW(IDS_ACCESS_TO_URL_WAS_DENIED), PLUGIN_WEB_URL);
1509                             break;
1510                         case SE_ERR_NOASSOC:
1511                             StringCbPrintfW(buf, sizeof(buf), WASABI_API_LNGSTRINGW(IDS_ACCESS_TO_URL_FAILED_DUE_TO_NO_ASSOC), PLUGIN_WEB_URL);
1512                             break;
1513                         default:
1514                             StringCbPrintfW(buf, sizeof(buf), WASABI_API_LNGSTRINGW(IDS_ACCESS_TO_URL_FAILED_CODE_X), PLUGIN_WEB_URL, ret);
1515                             break;
1516                         }
1517                         MessageBoxW(hwnd, buf, WASABI_API_LNGSTRINGW(IDS_ERROR_OPENING_URL), MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
1518                     }
1519                 }
1520                 break;
1521 
1522             case ID_DEFAULTS:
1523 				wchar_t title[64];
1524                 if (IDYES == MessageBoxW(hwnd, WASABI_API_LNGSTRINGW(IDS_RESTORE_ALL_DEFAULTS),
1525 										 WASABI_API_LNGSTRINGW_BUF(IDS_RESTORE_ALL_DEFAULTS_TITLE, title, 64),
1526 										 MB_YESNO|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL))
1527                 {
1528                     DeleteFileW(m_szConfigIniFile);
1529                     Sleep(100);
1530                     EndDialog(hwnd,id);
1531                 }
1532                 break;
1533 
1534             default:
1535                 return 0;
1536             }
1537         }
1538         break;        // case WM_COMMAND
1539 
1540     case WM_HELP:
1541         if (lParam)
1542 				{
1543 					HELPINFO *ph = (HELPINFO*)lParam;
1544 					wchar_t title[1024];
1545 					wchar_t buf[2048];
1546 					wchar_t ctrl_name[1024];
1547 					GetWindowTextW(GetDlgItem(hwnd, ph->iCtrlId), ctrl_name, sizeof(ctrl_name)/sizeof(*ctrl_name));
1548 					RemoveSingleAmpersands(ctrl_name);
1549 					buf[0] = 0;
1550 					switch(ph->iCtrlId)
1551 					{
1552 					case IDOK:
1553 						StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_BUTTON), ctrl_name);
1554 						WASABI_API_LNGSTRINGW_BUF(IDS_OK_HELP, buf, 2048);
1555 						break;
1556 
1557 					case IDCANCEL:
1558 						StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_BUTTON), ctrl_name);
1559 						WASABI_API_LNGSTRINGW_BUF(IDS_CANCEL_HELP, buf, 2048);
1560 						break;
1561 
1562 					case ID_DEFAULTS:
1563 						StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_BUTTON), ctrl_name);
1564 						WASABI_API_LNGSTRINGW_BUF(IDS_RESTORE_DEFAULTS_HELP, buf, 2048);
1565 						break;
1566 
1567 					case ID_DOCS:
1568 						StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_BUTTON), ctrl_name);
1569 						WASABI_API_LNGSTRINGW_BUF(IDS_DOCUMENTATION_BUTTON_HELP, buf, 2048);
1570 						break;
1571 
1572 					case ID_WEB:
1573 						StringCbPrintfW(title, sizeof(title), WASABI_API_LNGSTRINGW(IDS_HELP_ON_X_BUTTON), ctrl_name);
1574 						WASABI_API_LNGSTRINGW_BUF(IDS_VIEW_ONLINE_DOCS_HELP, buf, 2048);
1575 						break;
1576 
1577 					default:
1578 						return 0;
1579 					}
1580 
1581 					if (buf[0])
1582 						MessageBoxW(hwnd, buf, title, MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
1583 				}
1584         break;  // case WM_HELP
1585     }
1586 
1587     return 0;
1588 }