]> git.sesse.net Git - vlc/blob - modules/gui/wince/preferences.cpp
Remove stdlib.h
[vlc] / modules / gui / wince / preferences.cpp
1 /*****************************************************************************
2  * preferences.cpp : WinCE gui plugin for VLC
3  *****************************************************************************
4  * Copyright (C) 2000-2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Marodon Cedric <cedric_marodon@yahoo.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <string.h>                                            /* strerror() */
29 #include <stdio.h>
30 #include <vlc/vlc.h>
31 #include <vlc_interface.h>
32
33 #include "wince.h"
34
35 #include <winuser.h>
36 #include <windows.h>
37 #include <windowsx.h>
38 #include <commctrl.h>
39 #include <commdlg.h>
40
41 #include <vlc_config_cat.h>
42
43 #include "preferences_widgets.h"
44
45 #define GENERAL_ID 1242
46 #define PLUGIN_ID 1243
47 #define CAPABILITY_ID 1244
48
49 /*****************************************************************************
50  * Event Table.
51  *****************************************************************************/
52
53 /* IDs for the controls and the menu commands */
54 enum
55 {
56     Notebook_Event,
57     MRL_Event,
58     ResetAll_Event,
59     Advanced_Event
60 };
61
62 /*****************************************************************************
63  * Classes declarations.
64  *****************************************************************************/
65 class ConfigTreeData;
66 class PrefsTreeCtrl
67 {
68 public:
69
70     PrefsTreeCtrl() { }
71     PrefsTreeCtrl( intf_thread_t *_p_intf, PrefsDialog *p_prefs_dialog,
72                    HWND hwnd, HINSTANCE _hInst );
73     virtual ~PrefsTreeCtrl();
74
75     void ApplyChanges();
76     /*void CleanChanges();*/
77
78     void OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent, HINSTANCE hInst );
79         
80     ConfigTreeData *FindModuleConfig( ConfigTreeData *config_data );
81
82     HWND hwndTV;
83
84 private:
85     intf_thread_t *p_intf;
86     PrefsDialog *p_prefs_dialog;
87     vlc_bool_t b_advanced;
88
89     HTREEITEM general_item;
90     HTREEITEM plugins_item;
91 };
92
93 class PrefsPanel
94 {
95 public:
96
97     PrefsPanel() { }
98     PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
99                 PrefsDialog *, int i_object_id, char *, char * );
100     virtual ~PrefsPanel() {}
101
102     void Hide();
103     void Show();
104
105     HWND config_window;
106
107     int oldvalue;
108     int maxvalue;
109
110     void ApplyChanges();
111
112 private:
113     intf_thread_t *p_intf;
114     PrefsDialog *p_prefs_dialog;
115
116     vlc_bool_t b_advanced;
117
118     HWND label;
119
120     vector<ConfigControl *> config_array;
121 };
122
123 class ConfigTreeData
124 {
125 public:
126
127     ConfigTreeData() { b_submodule = 0; panel = NULL; psz_section = NULL;
128                        psz_help = NULL; }
129     virtual ~ConfigTreeData() { if( panel ) delete panel;
130                                 if( psz_section) free(psz_section);
131                                 if( psz_help) free(psz_help); }
132
133     vlc_bool_t b_submodule;
134
135     PrefsPanel *panel;
136     int i_object_id;
137     char *psz_section;
138     char *psz_help;
139 };
140
141 /*****************************************************************************
142  * Constructor.
143  *****************************************************************************/
144 PrefsDialog::PrefsDialog( intf_thread_t *p_intf, CBaseWindow *p_parent,
145                           HINSTANCE h_inst )
146   :  CBaseWindow( p_intf, p_parent, h_inst )
147 {
148     /* Initializations */
149     prefs_tree = NULL;
150 }
151
152 /***********************************************************************
153
154 FUNCTION: 
155   WndProc
156
157 PURPOSE: 
158   Processes messages sent to the main window.
159
160 ***********************************************************************/
161 LRESULT PrefsDialog::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
162 {
163     SHINITDLGINFO shidi;
164     SHMENUBARINFO mbi;
165     RECT rcClient;
166
167     switch( msg )
168     {
169     case WM_INITDIALOG:
170         shidi.dwMask = SHIDIM_FLAGS;
171         shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN |
172             SHIDIF_FULLSCREENNOMENUBAR;//SHIDIF_SIZEDLGFULLSCREEN;
173         shidi.hDlg = hwnd;
174         SHInitDialog( &shidi );
175
176         //Create the menubar
177         memset( &mbi, 0, sizeof (SHMENUBARINFO) );
178         mbi.cbSize     = sizeof (SHMENUBARINFO);
179         mbi.hwndParent = hwnd;
180         mbi.dwFlags    = SHCMBF_EMPTYBAR;
181         mbi.hInstRes   = hInst;
182
183         if( !SHCreateMenuBar(&mbi) )
184         {
185             MessageBox(hwnd, _T("SHCreateMenuBar Failed"), _T("Error"), MB_OK);
186             //return -1;
187         }
188
189         hwndCB = mbi.hwndMB;
190
191         // Get the client area rect to put the panels in
192         GetClientRect(hwnd, &rcClient);
193
194         /* Create the buttons */            
195         advanced_checkbox =
196             CreateWindow( _T("BUTTON"), _T("Advanced options"),
197                         WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
198                         5, 10, 15, 15, hwnd, NULL, hInst, NULL );
199         SendMessage( advanced_checkbox, BM_SETCHECK, BST_UNCHECKED, 0 );
200
201         advanced_label = CreateWindow( _T("STATIC"), _T("Advanced options"),
202                         WS_CHILD | WS_VISIBLE | SS_LEFT,
203                         5 + 15 + 5, 10, 110, 15,
204                         hwnd, NULL, hInst, NULL);
205
206         if( config_GetInt( p_intf, "advanced" ) )
207         {
208             SendMessage( advanced_checkbox, BM_SETCHECK, BST_CHECKED, 0 );
209             /*dummy_event.SetInt(TRUE);
210               OnAdvanced( dummy_event );*/
211         }
212
213         reset_button = CreateWindow( _T("BUTTON"), _T("Reset All"),
214                         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
215                         rcClient.right - 5 - 80, 10 - 3, 80, 15 + 6,
216                         hwnd, NULL, hInst, NULL );
217
218         /* Create the preferences tree control */
219         prefs_tree = new PrefsTreeCtrl( p_intf, this, hwnd, hInst );
220
221         UpdateWindow( hwnd );
222         break;
223
224     case WM_CLOSE:
225         EndDialog( hwnd, LOWORD( wp ) );
226         break;
227
228     case WM_SETFOCUS:
229         SHFullScreen( hwnd, SHFS_SHOWSIPBUTTON );
230         break;
231
232     case WM_COMMAND:
233         if( LOWORD(wp) == IDOK )
234         {
235             OnOk();
236             EndDialog( hwnd, LOWORD( wp ) );
237         }
238         break;
239
240     case WM_NOTIFY:
241
242         if( lp && prefs_tree &&
243             ((LPNMHDR)lp)->hwndFrom == prefs_tree->hwndTV &&
244             ((LPNMHDR)lp)->code == TVN_SELCHANGED )
245         {
246             prefs_tree->OnSelectTreeItem( (NM_TREEVIEW FAR *)(LPNMHDR)lp,
247                                           hwnd, hInst );
248         }
249         break;
250
251     case WM_VSCROLL:
252     {
253         TVITEM tvi = {0};
254         tvi.mask = TVIF_PARAM;
255         tvi.hItem = TreeView_GetSelection( prefs_tree->hwndTV );
256         if( !tvi.hItem ) break;
257
258         if( !TreeView_GetItem( prefs_tree->hwndTV, &tvi ) ) break;
259
260         ConfigTreeData *config_data =
261             prefs_tree->FindModuleConfig( (ConfigTreeData *)tvi.lParam );
262         if( config_data && hwnd == config_data->panel->config_window ) 
263         {
264             int dy;
265             RECT rc;
266             GetWindowRect( hwnd, &rc);
267             int newvalue = config_data->panel->oldvalue;
268             switch ( GET_WM_VSCROLL_CODE(wp,lp) ) 
269             {
270             case SB_BOTTOM       : newvalue = 0; break;
271             case SB_TOP          : newvalue = config_data->panel->maxvalue; break;
272             case SB_LINEDOWN     : newvalue += 10; break;
273             case SB_PAGEDOWN     : newvalue += rc.bottom - rc.top - 25; break; // wrong! one page is notebook actual length
274             case SB_LINEUP       : newvalue -= 10; break;
275             case SB_PAGEUP       : newvalue -= rc.bottom - rc.top - 25; break;
276             case SB_THUMBPOSITION:
277             case SB_THUMBTRACK   : newvalue = GET_WM_VSCROLL_POS(wp,lp); break;
278             }
279             newvalue = max(0,min(config_data->panel->maxvalue,newvalue));
280             SetScrollPos( hwnd,SB_VERT,newvalue,TRUE);//SB_CTL si hwnd=hwndScrollBar, SB_VERT si window
281             dy = config_data->panel->oldvalue - newvalue;
282
283             ScrollWindowEx( hwnd, 0, dy, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN );
284             UpdateWindow ( hwnd);
285
286             config_data->panel->oldvalue = newvalue;                                
287         }
288         break;
289     }
290
291     default:
292         break;
293     }
294
295     return FALSE;
296 }
297
298 /*****************************************************************************
299  * Private methods.
300  *****************************************************************************/
301
302 /*****************************************************************************
303  * Events methods.
304  *****************************************************************************/
305 void PrefsDialog::OnOk( void )
306 {
307     prefs_tree->ApplyChanges();
308     config_SaveConfigFile( p_intf, NULL );
309 }
310
311 /*****************************************************************************
312  * PrefsTreeCtrl class definition.
313  *****************************************************************************/
314 PrefsTreeCtrl::PrefsTreeCtrl( intf_thread_t *_p_intf,
315                               PrefsDialog *_p_prefs_dialog, HWND hwnd,
316                               HINSTANCE hInst )
317 {
318     vlc_list_t      *p_list;
319     module_t        *p_module;
320     module_config_t *p_item;
321     int i_index;
322
323     INITCOMMONCONTROLSEX iccex;
324     RECT rcClient;
325     TVITEM tvi = {0}; 
326     TVINSERTSTRUCT tvins = {0}; 
327     HTREEITEM hPrev;
328
329     size_t i_capability_count = 0;
330     size_t i_child_index;
331
332     HTREEITEM capability_item;
333
334     /* Initializations */
335     p_intf = _p_intf;
336     p_prefs_dialog = _p_prefs_dialog;
337     b_advanced = VLC_FALSE;
338
339     /* Create a tree view */
340     // Initialize the INITCOMMONCONTROLSEX structure.
341     iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
342     iccex.dwICC = ICC_TREEVIEW_CLASSES;
343
344     // Registers Statusbar control classes from the common control dll
345     InitCommonControlsEx( &iccex );
346
347     // Get the client area rect to put the tv in
348     GetClientRect(hwnd, &rcClient);
349
350     // Create the tree-view control.
351     hwndTV = CreateWindowEx( 0, WC_TREEVIEW, NULL,
352         WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES |
353         TVS_LINESATROOT | TVS_HASBUTTONS,
354         5, 10 + 2*(15 + 10) + 105 + 5, rcClient.right - 5 - 5, 6*15,
355         hwnd, NULL, hInst, NULL );
356
357     tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
358
359     /* List the plugins */
360     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
361     if( !p_list ) return;
362
363     /*
364      * Build a tree of the main options
365      */
366     ConfigTreeData *config_data = new ConfigTreeData;
367     config_data->i_object_id = GENERAL_ID;
368     config_data->psz_help = strdup("nothing");//strdup( GENERAL_HELP );
369     config_data->psz_section = strdup( GENERAL_TITLE );
370     tvi.pszText = _T("General settings");
371     tvi.cchTextMax = lstrlen(_T("General settings"));
372     tvi.lParam = (long)config_data;
373     tvins.item = tvi;
374     tvins.hInsertAfter = TVI_FIRST;
375     tvins.hParent = TVI_ROOT;
376
377     // Add the item to the tree-view control.
378     hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
379     general_item = hPrev;
380
381     for( i_index = 0; i_index < p_list->i_count; i_index++ )
382     {
383         p_module = (module_t *)p_list->p_values[i_index].p_object;
384         if( !strcmp( p_module->psz_object_name, "main" ) )
385             break;
386     }
387     if( i_index < p_list->i_count )
388     {
389         /* We found the main module */
390
391         /* Enumerate config categories and store a reference so we can
392          * generate their config panel them when it is asked by the user. */
393         p_item = p_module->p_config;
394
395         if( p_item ) do
396         {
397             switch( p_item->i_type )
398             {
399             case CONFIG_HINT_CATEGORY:
400                 ConfigTreeData *config_data = new ConfigTreeData;
401                 config_data->psz_section = strdup( p_item->psz_text );
402                 if( p_item->psz_longtext )
403                 {
404                     config_data->psz_help =
405                         strdup( p_item->psz_longtext );
406                 }
407                 else
408                 {
409                     config_data->psz_help = NULL;
410                 }
411                 config_data->i_object_id = p_module->i_object_id;
412
413                 /* Add the category to the tree */
414                 // Set the text of the item. 
415                 tvi.pszText = _FROMMB(p_item->psz_text); 
416                 tvi.cchTextMax = _tcslen(tvi.pszText);
417                 tvi.lParam = (long)config_data;
418                 tvins.item = tvi;
419                 tvins.hInsertAfter = hPrev; 
420                 tvins.hParent = general_item; //level 3
421     
422                 // Add the item to the tree-view control. 
423                 hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );
424
425                 break;
426             }
427         }
428         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
429
430         TreeView_SortChildren( hwndTV, general_item, 0 );
431     }
432         
433     /*
434      * Build a tree of all the plugins
435      */
436     config_data = new ConfigTreeData;
437     config_data->i_object_id = PLUGIN_ID;
438     config_data->psz_help = strdup("nothing");//strdup( PLUGIN_HELP );
439     config_data->psz_section = strdup("nothing");//strdup( PLUGIN_TITLE );
440     tvi.pszText = _T("Modules");
441     tvi.cchTextMax = lstrlen(_T("Modules"));
442     tvi.lParam = (long)config_data;
443     tvins.item = tvi;
444     tvins.hInsertAfter = TVI_LAST;
445     tvins.hParent = TVI_ROOT;
446
447     // Add the item to the tree-view control.
448     hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
449     plugins_item = hPrev;
450
451     i_capability_count = 0;
452     for( i_index = 0; i_index < p_list->i_count; i_index++ )
453     {
454         i_child_index = 0;
455
456         p_module = (module_t *)p_list->p_values[i_index].p_object;
457
458         /* Exclude the main module */
459         if( !strcmp( p_module->psz_object_name, "main" ) )
460             continue;
461
462         /* Exclude empty plugins (submodules don't have config options, they
463          * are stored in the parent module) */
464         if( p_module->b_submodule )
465             p_item = ((module_t *)p_module->p_parent)->p_config;
466         else
467             p_item = p_module->p_config;
468
469         if( !p_item ) continue;
470         do
471         {
472             if( p_item->i_type & CONFIG_ITEM )
473                 break;
474         }
475         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
476         if( p_item->i_type == CONFIG_HINT_END ) continue;
477
478         /* Find the capability child item */
479         /*long cookie; size_t i_child_index;*/
480         capability_item = TreeView_GetChild( hwndTV, plugins_item );
481         while( capability_item != 0 )
482         {
483             TVITEM capability_tvi = {0};
484             TCHAR psz_text[256];
485             i_child_index++;
486
487             capability_tvi.mask = TVIF_TEXT;
488             capability_tvi.pszText = psz_text;
489             capability_tvi.cchTextMax = 256;
490             capability_tvi.hItem = capability_item;
491             TreeView_GetItem( hwndTV, &capability_tvi );
492             if( !strcmp( _TOMB(capability_tvi.pszText),
493                          p_module->psz_capability ) ) break;
494  
495             capability_item =
496                 TreeView_GetNextSibling( hwndTV, capability_item );
497         }
498
499         if( i_child_index == i_capability_count &&
500             p_module->psz_capability && *p_module->psz_capability )
501         {
502             /* We didn't find it, add it */
503             ConfigTreeData *config_data = new ConfigTreeData;
504             config_data->psz_section =
505                 strdup( GetCapabilityHelp( p_module->psz_capability , 1 ) );
506             config_data->psz_help =
507                 strdup( GetCapabilityHelp( p_module->psz_capability , 2 ) );
508             config_data->i_object_id = CAPABILITY_ID;
509             tvi.pszText = _FROMMB(p_module->psz_capability);
510             tvi.cchTextMax = _tcslen(tvi.pszText);
511             tvi.lParam = (long)config_data;
512             tvins.item = tvi;
513             tvins.hInsertAfter = plugins_item; 
514             tvins.hParent = plugins_item;// level 3
515
516             // Add the item to the tree-view control. 
517             capability_item = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
518
519             i_capability_count++;
520         }
521
522         /* Add the plugin to the tree */
523         ConfigTreeData *config_data = new ConfigTreeData;
524         config_data->b_submodule = p_module->b_submodule;
525         config_data->i_object_id = p_module->b_submodule ?
526             ((module_t *)p_module->p_parent)->i_object_id :
527             p_module->i_object_id;
528         config_data->psz_help = NULL;
529         tvi.pszText = _FROMMB(p_module->psz_object_name);
530         tvi.cchTextMax = _tcslen(tvi.pszText);
531         tvi.lParam = (long)config_data;
532         tvins.item = tvi;
533         tvins.hInsertAfter = capability_item; 
534         tvins.hParent = capability_item;// level 4
535
536         // Add the item to the tree-view control. 
537         TreeView_InsertItem( hwndTV, &tvins );
538     }
539
540     /* Sort all this mess */
541     /*long cookie; size_t i_child_index;*/
542     TreeView_SortChildren( hwndTV, plugins_item, 0 );
543     capability_item = TreeView_GetChild( hwndTV, plugins_item );
544     while( capability_item != 0 )
545     {
546         TreeView_SortChildren( hwndTV, capability_item, 0 );
547         capability_item = TreeView_GetNextSibling( hwndTV, capability_item );
548     }
549
550     /* Clean-up everything */
551     vlc_list_release( p_list );
552
553     TreeView_Expand( hwndTV, general_item, TVE_EXPANDPARTIAL |TVE_EXPAND );
554 }
555
556 PrefsTreeCtrl::~PrefsTreeCtrl()
557 {
558 }
559
560 void PrefsTreeCtrl::ApplyChanges()
561 {
562     /*long cookie, cookie2;*/
563     ConfigTreeData *config_data;
564
565     /* Apply changes to the main module */
566     HTREEITEM item = TreeView_GetChild( hwndTV, general_item );
567     while( item != 0 )
568     {
569         TVITEM tvi = {0};
570         tvi.mask = TVIF_PARAM;
571         tvi.hItem = item;
572         TreeView_GetItem( hwndTV, &tvi );
573         config_data = (ConfigTreeData *)tvi.lParam;
574         if( config_data && config_data->panel )
575         {
576             config_data->panel->ApplyChanges();
577         }
578
579         item = TreeView_GetNextSibling( hwndTV, item );
580     }
581
582     /* Apply changes to the plugins */
583     item = TreeView_GetChild( hwndTV, plugins_item );
584     while( item != 0 )
585     {
586         HTREEITEM item2 = TreeView_GetChild( hwndTV, item );
587         while( item2 != 0 )
588         {       
589             TVITEM tvi = {0};
590             tvi.mask = TVIF_PARAM;
591             tvi.hItem = item2;
592             TreeView_GetItem( hwndTV, &tvi );
593             config_data = (ConfigTreeData *)tvi.lParam;
594             if( config_data && config_data->panel )
595             {
596                 config_data->panel->ApplyChanges();
597             }
598             item2 = TreeView_GetNextSibling( hwndTV, item2 );
599         }
600         item = TreeView_GetNextSibling( hwndTV, item );
601     }
602 }
603
604 ConfigTreeData *PrefsTreeCtrl::FindModuleConfig( ConfigTreeData *config_data )
605 {
606     /* We need this complexity because submodules don't have their own config
607      * options. They use the parent module ones. */
608
609     if( !config_data || !config_data->b_submodule )
610     {
611         return config_data;
612     }
613
614     /*long cookie, cookie2;*/
615     ConfigTreeData *config_new;
616     HTREEITEM item = TreeView_GetChild( hwndTV, plugins_item );
617     while( item != 0 )
618     {
619         HTREEITEM item2 = TreeView_GetChild( hwndTV, item );
620         while( item2 != 0 )
621         {       
622             TVITEM tvi = {0};
623             tvi.mask = TVIF_PARAM;
624             tvi.hItem = item2;
625             TreeView_GetItem( hwndTV, &tvi );
626             config_new = (ConfigTreeData *)tvi.lParam;
627             if( config_new && !config_new->b_submodule &&
628                 config_new->i_object_id == config_data->i_object_id )
629             {
630                 return config_new;
631             }
632             item2 = TreeView_GetNextSibling( hwndTV, item2 );
633         }
634         item = TreeView_GetNextSibling( hwndTV, item );
635     }
636
637     /* Found nothing */
638     return NULL;
639 }
640
641 void PrefsTreeCtrl::OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent,
642                                       HINSTANCE hInst )
643 {
644     ConfigTreeData *config_data = NULL;
645
646     if( pnmtv->itemOld.hItem )
647         config_data = FindModuleConfig( (ConfigTreeData *)pnmtv->itemOld.lParam );
648
649     if( config_data && config_data->panel )
650     {
651         config_data->panel->Hide();
652     }
653
654     /* Don't use event.GetItem() because we also send fake events */
655     TVITEM tvi = {0};
656     tvi.mask = TVIF_PARAM;
657     tvi.hItem = TreeView_GetSelection( hwndTV );
658     TreeView_GetItem( hwndTV, &tvi );
659     config_data = FindModuleConfig( (ConfigTreeData *)tvi.lParam );
660     if( config_data )
661     {
662         if( !config_data->panel )
663         {
664             /* The panel hasn't been created yet. Let's do it. */
665             config_data->panel =
666                 new PrefsPanel( parent, hInst, p_intf, p_prefs_dialog,
667                                 config_data->i_object_id,
668                                 config_data->psz_section,
669                                 config_data->psz_help );
670         }
671         else
672         {
673             config_data->panel->Show();
674         }
675     }
676 }
677
678 /*****************************************************************************
679  * PrefsPanel class definition.
680  *****************************************************************************/
681 PrefsPanel::PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
682                         PrefsDialog *_p_prefs_dialog,
683                         int i_object_id, char *psz_section, char *psz_help )
684 {
685     module_config_t *p_item;
686     module_t *p_module = NULL;
687
688     /* Initializations */
689     p_intf = _p_intf;
690     p_prefs_dialog = _p_prefs_dialog;
691
692     b_advanced = VLC_TRUE;
693
694     if( i_object_id == PLUGIN_ID || i_object_id == GENERAL_ID ||
695         i_object_id == CAPABILITY_ID )
696     {
697         label = CreateWindow( _T("STATIC"), _FROMMB(psz_section),
698                               WS_CHILD | WS_VISIBLE | SS_LEFT,
699                               5, 10 + (15 + 10), 200, 15,
700                               parent, NULL, hInst, NULL );
701         config_window = NULL;
702     }
703     else
704     {
705         /* Get a pointer to the module */
706         p_module = (module_t *)vlc_object_get( p_intf,  i_object_id );
707         if( p_module->i_object_type != VLC_OBJECT_MODULE )
708         {
709             /* 0OOoo something went really bad */
710             return;
711         }
712
713         /* Enumerate config options and add corresponding config boxes
714          * (submodules don't have config options, they are stored in the
715          *  parent module) */
716         if( p_module->b_submodule )
717             p_item = ((module_t *)p_module->p_parent)->p_config;
718         else
719             p_item = p_module->p_config;
720
721         /* Find the category if it has been specified */
722         if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY )
723         {
724             while( !(p_item->i_type == CONFIG_HINT_CATEGORY) ||
725                    strcmp( psz_section, p_item->psz_text ) )
726             {
727                 if( p_item->i_type == CONFIG_HINT_END ) break;
728                 p_item++;
729             }
730         }
731
732         /* Add a head title to the panel */
733         label = CreateWindow( _T("STATIC"), _FROMMB(psz_section ?
734                         p_item->psz_text : p_module->psz_longname),
735                         WS_CHILD | WS_VISIBLE | SS_LEFT,
736                         5, 10 + (15 + 10), 250, 15,
737                         parent, NULL, hInst, NULL );
738
739         WNDCLASS wc;
740         memset( &wc, 0, sizeof(wc) );
741         wc.style          = CS_HREDRAW | CS_VREDRAW;
742         wc.lpfnWndProc    = (WNDPROC) _p_prefs_dialog->BaseWndProc;
743         wc.cbClsExtra     = 0;
744         wc.cbWndExtra     = 0;
745         wc.hInstance      = hInst;
746         wc.hIcon          = 0;
747         wc.hCursor        = 0;
748         wc.hbrBackground  = (HBRUSH) GetStockObject(WHITE_BRUSH);
749         wc.lpszMenuName   = 0;
750         wc.lpszClassName  = _T("PrefsPanelClass");
751         RegisterClass(&wc);
752
753         RECT rc;
754         GetWindowRect( parent, &rc);
755         config_window = CreateWindow( _T("PrefsPanelClass"),
756                         _T("config_window"),
757                         WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER,
758                         5, 10 + 2*(15 + 10), rc.right - 5 - 7, 105,
759                         parent, NULL, hInst, (void *) _p_prefs_dialog );
760
761         int y_pos = 5;
762         if( p_item ) do
763         {
764             /* If a category has been specified, check we finished the job */
765             if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY &&
766                 strcmp( psz_section, p_item->psz_text ) )
767                 break;
768
769             ConfigControl *control =
770                 CreateConfigControl( VLC_OBJECT(p_intf),
771                                      p_item, config_window,
772                                      hInst, &y_pos );
773
774             /* Don't add items that were not recognized */
775             if( control == NULL ) continue;
776
777             /* Add the config data to our array so we can keep a trace of it */
778             config_array.push_back( control );
779         }
780         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
781                 
782         GetWindowRect( config_window, &rc);
783         maxvalue = y_pos - (rc.bottom - rc.top) + 5;
784         oldvalue = 0;
785         SetScrollRange( config_window, SB_VERT, 0, maxvalue, TRUE );
786     }
787 }
788
789 void PrefsPanel::Hide()
790 {
791     ShowWindow( label, SW_HIDE );
792     if( config_window ) ShowWindow( config_window, SW_HIDE );
793 }
794
795 void PrefsPanel::Show()
796 {
797     ShowWindow( label, SW_SHOW );
798     if( config_window ) ShowWindow( config_window, SW_SHOW );
799 }
800
801 void PrefsPanel::ApplyChanges()
802 {
803     vlc_value_t val;
804
805     for( size_t i = 0; i < config_array.size(); i++ )
806     {
807         ConfigControl *control = config_array[i];
808
809         switch( control->GetType() )
810         {
811         case CONFIG_ITEM_STRING:
812         case CONFIG_ITEM_FILE:
813         case CONFIG_ITEM_DIRECTORY:
814         case CONFIG_ITEM_MODULE:
815             config_PutPsz( p_intf, control->GetName(),
816                            control->GetPszValue() );
817             break;
818         case CONFIG_ITEM_KEY:
819             /* So you don't need to restart to have the changes take effect */
820             val.i_int = control->GetIntValue();
821             var_Set( p_intf->p_libvlc, control->GetName(), val );
822         case CONFIG_ITEM_INTEGER:
823         case CONFIG_ITEM_BOOL:
824             config_PutInt( p_intf, control->GetName(),
825                            control->GetIntValue() );
826             break;
827         case CONFIG_ITEM_FLOAT:
828             config_PutFloat( p_intf, control->GetName(),
829                              control->GetFloatValue() );
830             break;
831         }
832     }
833 }