]> git.sesse.net Git - vlc/blob - modules/gui/macosx/prefs_widgets.m
macosx: fixed l10n of the Growl option
[vlc] / modules / gui / macosx / prefs_widgets.m
1 /*****************************************************************************
2  * prefs_widgets.m: Preferences controls
3  *****************************************************************************
4  * Copyright (C) 2002-2011 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Derk-Jan Hartman <hartman at videolan.org>
8  *          Jérôme Decoodt <djc at 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 <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <vlc_common.h>
36 #include <vlc_modules.h>
37 #include <vlc_keys.h>
38
39 #include "intf.h"
40 #include "prefs_widgets.h"
41
42 #define PREFS_WRAP 300
43 #define OFFSET_RIGHT 20
44 #define OFFSET_BETWEEN 2
45
46 #define UPWARDS_WHITE_ARROW                 "\xE2\x87\xA7"
47 #define OPTION_KEY                          "\xE2\x8C\xA5"
48 #define UP_ARROWHEAD                        "\xE2\x8C\x83"
49 #define PLACE_OF_INTEREST_SIGN              "\xE2\x8C\x98"
50
51 #define POPULATE_A_KEY( o_menu, string, value )                             \
52 {                                                                           \
53     NSMenuItem *o_mi;                                                       \
54 /*  Normal */                                                               \
55     o_mi = [[NSMenuItem alloc] initWithTitle:string                         \
56         action:nil keyEquivalent:@""];                                      \
57     [o_mi setKeyEquivalentModifierMask:                                     \
58         0];                                                                 \
59     [o_mi setAlternate: NO];                                                \
60     [o_mi setTag:                                                           \
61         ( value )];                                                         \
62     [o_menu addItem: o_mi];                                                 \
63 /*  Ctrl */                                                                 \
64     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
65         [[NSString stringWithUTF8String:                                    \
66             UP_ARROWHEAD                                                    \
67         ] stringByAppendingString: string]                                  \
68         action:nil keyEquivalent:@""];                                      \
69     [o_mi setKeyEquivalentModifierMask:                                     \
70         NSControlKeyMask];                                                  \
71     [o_mi setAlternate: YES];                                               \
72     [o_mi setTag:                                                           \
73         KEY_MODIFIER_CTRL | ( value )];                                     \
74     [o_menu addItem: o_mi];                                                 \
75 /* Ctrl+Alt */                                                              \
76     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
77         [[NSString stringWithUTF8String:                                    \
78             UP_ARROWHEAD OPTION_KEY                                         \
79         ] stringByAppendingString: string]                                  \
80         action:nil keyEquivalent:@""];                                      \
81     [o_mi setKeyEquivalentModifierMask:                                     \
82         NSControlKeyMask | NSAlternateKeyMask];                             \
83     [o_mi setAlternate: YES];                                               \
84     [o_mi setTag:                                                           \
85         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT) | ( value )];                \
86     [o_menu addItem: o_mi];                                                 \
87 /* Ctrl+Shift */                                                            \
88     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
89         [[NSString stringWithUTF8String:                                    \
90             UP_ARROWHEAD UPWARDS_WHITE_ARROW                                \
91         ] stringByAppendingString: string]                                  \
92         action:nil keyEquivalent:@""];                                      \
93     [o_mi setKeyEquivalentModifierMask:                                     \
94        NSControlKeyMask | NSShiftKeyMask];                                  \
95     [o_mi setAlternate: YES];                                               \
96     [o_mi setTag:                                                           \
97         (KEY_MODIFIER_CTRL | KEY_MODIFIER_SHIFT) | ( value )];              \
98     [o_menu addItem: o_mi];                                                 \
99 /* Ctrl+Apple */                                                            \
100     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
101         [[NSString stringWithUTF8String:                                    \
102             UP_ARROWHEAD PLACE_OF_INTEREST_SIGN                             \
103         ] stringByAppendingString: string]                                  \
104         action:nil keyEquivalent:@""];                                      \
105     [o_mi setKeyEquivalentModifierMask:                                     \
106         NSControlKeyMask | NSCommandKeyMask];                               \
107     [o_mi setAlternate: YES];                                               \
108     [o_mi setTag:                                                           \
109         (KEY_MODIFIER_CTRL | KEY_MODIFIER_COMMAND) | ( value )];            \
110     [o_menu addItem: o_mi];                                                 \
111 /* Ctrl+Alt+Shift */                                                        \
112     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
113         [[NSString stringWithUTF8String:                                    \
114             UP_ARROWHEAD OPTION_KEY UPWARDS_WHITE_ARROW                     \
115         ] stringByAppendingString: string]                                  \
116         action:nil keyEquivalent:@""];                                      \
117     [o_mi setKeyEquivalentModifierMask:                                     \
118         NSControlKeyMask | NSAlternateKeyMask | NSShiftKeyMask];            \
119     [o_mi setAlternate: YES];                                               \
120     [o_mi setTag:                                                           \
121         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT) |       \
122              ( value )];                                                    \
123     [o_menu addItem: o_mi];                                                 \
124 /* Ctrl+Alt+Apple */                                                        \
125     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
126         [[NSString stringWithUTF8String:                                    \
127             UP_ARROWHEAD OPTION_KEY PLACE_OF_INTEREST_SIGN                  \
128         ] stringByAppendingString: string]                                  \
129         action:nil keyEquivalent:@""];                                      \
130     [o_mi setKeyEquivalentModifierMask:                                     \
131         NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask];          \
132     [o_mi setAlternate: YES];                                               \
133     [o_mi setTag:                                                           \
134         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT | KEY_MODIFIER_COMMAND) |     \
135             ( value )];                                                     \
136     [o_menu addItem: o_mi];                                                 \
137 /* Ctrl+Shift+Apple */                                                      \
138     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
139         [[NSString stringWithUTF8String:                                    \
140             UP_ARROWHEAD UPWARDS_WHITE_ARROW PLACE_OF_INTEREST_SIGN         \
141         ] stringByAppendingString: string]                                  \
142         action:nil keyEquivalent:@""];                                      \
143     [o_mi setKeyEquivalentModifierMask:                                     \
144         NSControlKeyMask | NSShiftKeyMask | NSCommandKeyMask];              \
145     [o_mi setAlternate: YES];                                               \
146     [o_mi setTag:                                                           \
147         (KEY_MODIFIER_CTRL | KEY_MODIFIER_SHIFT | KEY_MODIFIER_COMMAND) |   \
148             ( value )];                                                     \
149     [o_menu addItem: o_mi];                                                 \
150 /* Ctrl+Alt+Shift+Apple */                                                  \
151     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
152         [[NSString stringWithUTF8String:                                    \
153             UP_ARROWHEAD OPTION_KEY UPWARDS_WHITE_ARROW                     \
154                 PLACE_OF_INTEREST_SIGN                                      \
155         ] stringByAppendingString: string]                                  \
156         action:nil keyEquivalent:@""];                                      \
157     [o_mi setKeyEquivalentModifierMask:                                     \
158         NSControlKeyMask | NSAlternateKeyMask | NSShiftKeyMask |            \
159             NSCommandKeyMask];                                              \
160     [o_mi setAlternate: YES];                                               \
161     [o_mi setTag:                                                           \
162         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT |        \
163             KEY_MODIFIER_COMMAND) | ( value )];                             \
164     [o_menu addItem: o_mi];                                                 \
165 /* Alt */                                                                   \
166     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
167         [[NSString stringWithUTF8String:                                    \
168             OPTION_KEY                                                      \
169         ] stringByAppendingString: string]                                  \
170         action:nil keyEquivalent:@""];                                      \
171     [o_mi setKeyEquivalentModifierMask:                                     \
172         NSAlternateKeyMask];                                                \
173     [o_mi setAlternate: YES];                                               \
174     [o_mi setTag:                                                           \
175         KEY_MODIFIER_ALT | ( value )];                                      \
176     [o_menu addItem: o_mi];                                                 \
177 /* Alt+Shift */                                                             \
178     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
179         [[NSString stringWithUTF8String:                                    \
180             OPTION_KEY UPWARDS_WHITE_ARROW                                  \
181         ] stringByAppendingString: string]                                  \
182         action:nil keyEquivalent:@""];                                      \
183     [o_mi setKeyEquivalentModifierMask:                                     \
184         NSAlternateKeyMask | NSShiftKeyMask];                               \
185     [o_mi setAlternate: YES];                                               \
186     [o_mi setTag:                                                           \
187         (KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT) | ( value )];               \
188     [o_menu addItem: o_mi];                                                 \
189 /* Alt+Apple */                                                             \
190     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
191         [[NSString stringWithUTF8String:                                    \
192             OPTION_KEY PLACE_OF_INTEREST_SIGN                               \
193         ] stringByAppendingString: string]                                  \
194         action:nil keyEquivalent:@""];                                      \
195     [o_mi setKeyEquivalentModifierMask:                                     \
196         NSAlternateKeyMask | NSCommandKeyMask];                             \
197     [o_mi setAlternate: YES];                                               \
198     [o_mi setTag:                                                           \
199         (KEY_MODIFIER_ALT | KEY_MODIFIER_COMMAND) | ( value )];             \
200     [o_menu addItem: o_mi];                                                 \
201 /* Alt+Shift+Apple */                                                       \
202     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
203         [[NSString stringWithUTF8String:                                    \
204             OPTION_KEY UPWARDS_WHITE_ARROW PLACE_OF_INTEREST_SIGN           \
205         ] stringByAppendingString: string]                                  \
206         action:nil keyEquivalent:@""];                                      \
207     [o_mi setKeyEquivalentModifierMask:                                     \
208         NSAlternateKeyMask | NSShiftKeyMask | NSCommandKeyMask];            \
209     [o_mi setAlternate: YES];                                               \
210     [o_mi setTag:                                                           \
211         (KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT | KEY_MODIFIER_COMMAND) |    \
212             ( value )];                                                     \
213     [o_menu addItem: o_mi];                                                 \
214 /* Shift */                                                                 \
215     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
216         [[NSString stringWithUTF8String:                                    \
217             UPWARDS_WHITE_ARROW                                             \
218         ] stringByAppendingString: string]                                  \
219         action:nil keyEquivalent:@""];                                      \
220     [o_mi setKeyEquivalentModifierMask:                                     \
221         NSShiftKeyMask];                                                    \
222     [o_mi setAlternate: YES];                                               \
223     [o_mi setTag:                                                           \
224         KEY_MODIFIER_SHIFT | ( value )];                                    \
225     [o_menu addItem: o_mi];                                                 \
226 /* Shift+Apple */                                                           \
227     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
228         [[NSString stringWithUTF8String:                                    \
229             UPWARDS_WHITE_ARROW PLACE_OF_INTEREST_SIGN                      \
230         ] stringByAppendingString: string]                                  \
231         action:nil keyEquivalent:@""];                                      \
232     [o_mi setKeyEquivalentModifierMask:                                     \
233         NSShiftKeyMask | NSCommandKeyMask];                                 \
234     [o_mi setAlternate: YES];                                               \
235     [o_mi setTag:                                                           \
236         (KEY_MODIFIER_SHIFT | KEY_MODIFIER_COMMAND) | ( value )];           \
237     [o_menu addItem: o_mi];                                                 \
238 /* Apple */                                                                 \
239     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
240         [[NSString stringWithUTF8String:                                    \
241         PLACE_OF_INTEREST_SIGN                                              \
242         ] stringByAppendingString: string]                                  \
243         action:nil keyEquivalent:@""];                                      \
244     [o_mi setKeyEquivalentModifierMask:                                     \
245         NSCommandKeyMask];                                                  \
246     [o_mi setAlternate: YES];                                               \
247     [o_mi setTag:                                                           \
248         KEY_MODIFIER_COMMAND | ( value )];                                  \
249     [o_menu addItem: o_mi];                                                 \
250 }
251
252 #define ADD_LABEL( o_label, superFrame, x_offset, my_y_offset, label,       \
253     tooltip )                                                               \
254 {                                                                           \
255     NSRect s_rc = superFrame;                                               \
256     s_rc.size.height = 17;                                                  \
257     s_rc.origin.x = x_offset - 3;                                           \
258     s_rc.origin.y = superFrame.size.height - 17 + my_y_offset;              \
259     o_label = [[[NSTextField alloc] initWithFrame: s_rc] retain];           \
260     [o_label setDrawsBackground: NO];                                       \
261     [o_label setBordered: NO];                                              \
262     [o_label setEditable: NO];                                              \
263     [o_label setSelectable: NO];                                            \
264     [o_label setStringValue: label];                                        \
265     [o_label setToolTip: tooltip];                                          \
266     [o_label setFont:[NSFont systemFontOfSize:0]];                          \
267     [o_label sizeToFit];                                                    \
268 }
269
270 #define ADD_TEXTFIELD( o_textfield, superFrame, x_offset, my_y_offset,      \
271     my_width, tooltip, init_value )                                         \
272 {                                                                           \
273     NSRect s_rc = superFrame;                                               \
274     s_rc.origin.x = x_offset;                                               \
275     s_rc.origin.y = my_y_offset;                                            \
276     s_rc.size.height = 22;                                                  \
277     s_rc.size.width = my_width;                                             \
278     o_textfield = [[[NSTextField alloc] initWithFrame: s_rc] retain];       \
279     [o_textfield setFont:[NSFont systemFontOfSize:0]];                      \
280     [o_textfield setToolTip: tooltip];                                      \
281     [o_textfield setStringValue: init_value];                               \
282 }
283
284 #define ADD_SECURETEXTFIELD( o_textfield, superFrame, x_offset, my_y_offset,      \
285 my_width, tooltip, init_value )                                         \
286 {                                                                           \
287 NSRect s_rc = superFrame;                                               \
288 s_rc.origin.x = x_offset;                                               \
289 s_rc.origin.y = my_y_offset;                                            \
290 s_rc.size.height = 22;                                                  \
291 s_rc.size.width = my_width;                                             \
292 o_textfield = [[[NSSecureTextField alloc] initWithFrame: s_rc] retain];       \
293 [o_textfield setFont:[NSFont systemFontOfSize:0]];                      \
294 [o_textfield setToolTip: tooltip];                                      \
295 [o_textfield setStringValue: init_value];                               \
296 }
297
298 #define ADD_COMBO( o_combo, superFrame, x_offset, my_y_offset, x2_offset,   \
299     tooltip )                                                               \
300 {                                                                           \
301     NSRect s_rc = superFrame;                                               \
302     s_rc.origin.x = x_offset + 2;                                           \
303     s_rc.origin.y = my_y_offset;                                            \
304     s_rc.size.height = 26;                                                  \
305     s_rc.size.width = superFrame.size.width + 2 - s_rc.origin.x -           \
306         (x2_offset);                                                        \
307     o_combo = [[[NSComboBox alloc] initWithFrame: s_rc] retain];            \
308     [o_combo setFont:[NSFont systemFontOfSize:0]];                          \
309     [o_combo setToolTip: tooltip];                                          \
310     [o_combo setUsesDataSource:TRUE];                                       \
311     [o_combo setDataSource:self];                                           \
312     [o_combo setNumberOfVisibleItems:10];                                   \
313     [o_combo setCompletes:YES];                                             \
314 }
315
316 #define ADD_RIGHT_BUTTON( o_button, superFrame, x_offset, my_y_offset,      \
317     tooltip, title )                                                        \
318 {                                                                           \
319     NSRect s_rc = superFrame;                                               \
320     o_button = [[[NSButton alloc] initWithFrame: s_rc] retain];             \
321     [o_button setButtonType: NSMomentaryPushInButton];                      \
322     [o_button setBezelStyle: NSRoundedBezelStyle];                          \
323     [o_button setTitle: title];                                             \
324     [o_button setFont:[NSFont systemFontOfSize:0]];                         \
325     [o_button sizeToFit];                                                   \
326     s_rc = [o_button frame];                                                \
327     s_rc.origin.x = superFrame.size.width - [o_button frame].size.width - 6;\
328     s_rc.origin.y = my_y_offset - 6;                                        \
329     s_rc.size.width += 12;                                                  \
330     [o_button setFrame: s_rc];                                              \
331     [o_button setToolTip: tooltip];                                         \
332     [o_button setTarget: self];                                             \
333     [o_button setAction: @selector(openFileDialog:)];                       \
334 }
335
336 #define ADD_POPUP( o_popup, superFrame, x_offset, my_y_offset, x2_offset,   \
337     tooltip )                                                               \
338 {                                                                           \
339     NSRect s_rc = superFrame;                                               \
340     s_rc.origin.x = x_offset - 1;                                           \
341     s_rc.origin.y = my_y_offset;                                            \
342     s_rc.size.height = 26;                                                  \
343     s_rc.size.width = superFrame.size.width + 2 - s_rc.origin.x -           \
344         (x2_offset);                                                        \
345     o_popup = [[[NSPopUpButton alloc] initWithFrame: s_rc] retain];         \
346     [o_popup setFont:[NSFont systemFontOfSize:0]];                          \
347     [o_popup setToolTip: tooltip];                                          \
348 }
349
350 #define ADD_STEPPER( o_stepper, superFrame, x_offset, my_y_offset, tooltip, \
351     lower, higher )                                                         \
352 {                                                                           \
353     NSRect s_rc = superFrame;                                               \
354     s_rc.origin.x = x_offset;                                               \
355     s_rc.origin.y = my_y_offset;                                            \
356     s_rc.size.height = 23;                                                  \
357     s_rc.size.width = 23;                                                   \
358     o_stepper = [[[NSStepper alloc] initWithFrame: s_rc] retain];           \
359     [o_stepper setFont:[NSFont systemFontOfSize:0]];                        \
360     [o_stepper setToolTip: tooltip];                                        \
361     [o_stepper setMaxValue: higher];                                        \
362     [o_stepper setMinValue: lower];                                         \
363     [o_stepper setTarget: self];                                            \
364     [o_stepper setAction: @selector(stepperChanged:)];                      \
365     [o_stepper sendActionOn:NSLeftMouseUpMask | NSLeftMouseDownMask |       \
366         NSLeftMouseDraggedMask];                                            \
367 }
368
369 #define ADD_SLIDER( o_slider, superFrame, x_offset, my_y_offset, my_width,  \
370     tooltip, lower, higher )                                                \
371 {                                                                           \
372     NSRect s_rc = superFrame;                                               \
373     s_rc.origin.x = x_offset;                                               \
374     s_rc.origin.y = my_y_offset;                                            \
375     s_rc.size.height = 21;                                                  \
376     s_rc.size.width = my_width;                                             \
377     o_slider = [[[NSSlider alloc] initWithFrame: s_rc] retain];             \
378     [o_slider setFont:[NSFont systemFontOfSize:0]];                         \
379     [o_slider setToolTip: tooltip];                                         \
380     [o_slider setMaxValue: higher];                                         \
381     [o_slider setMinValue: lower];                                          \
382 }
383
384 #define ADD_CHECKBOX( o_checkbox, superFrame, x_offset, my_y_offset, label, \
385     tooltip, init_value, position )                                         \
386 {                                                                           \
387     NSRect s_rc = superFrame;                                               \
388     s_rc.size.height = 18;                                                  \
389     s_rc.origin.x = x_offset - 2;                                           \
390     s_rc.origin.y = superFrame.size.height - 18 + my_y_offset;              \
391     o_checkbox = [[[NSButton alloc] initWithFrame: s_rc] retain];           \
392     [o_checkbox setFont:[NSFont systemFontOfSize:0]];                       \
393     [o_checkbox setButtonType: NSSwitchButton];                             \
394     [o_checkbox setImagePosition: position];                                \
395     [o_checkbox setIntValue: init_value];                                   \
396     [o_checkbox setTitle: label];                                           \
397     [o_checkbox setToolTip: tooltip];                                       \
398     [o_checkbox sizeToFit];                                                 \
399 }
400
401 @implementation VLCConfigControl
402 - (id)initWithFrame: (NSRect)frame
403 {
404     return [self initWithFrame: frame
405                     item: nil];
406 }
407
408 - (id)initWithFrame: (NSRect)frame
409         item: (module_config_t *)_p_item
410 {
411     self = [super initWithFrame: frame];
412
413     if( self != nil )
414     {
415         p_item = _p_item;
416         psz_name = p_item->psz_name;
417         o_label = NULL;
418         i_type = p_item->i_type;
419         i_view_type = 0;
420         b_advanced = p_item->b_advanced;
421         [self setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin ];
422     }
423     return (self);
424 }
425
426 - (void)setYPos:(int)i_yPos
427 {
428     NSRect frame = [self frame];
429     frame.origin.y = i_yPos;
430     [self setFrame:frame];
431 }
432
433 - (void)dealloc
434 {
435     if( o_label ) [o_label release];
436     free( psz_name );
437     [super dealloc];
438 }
439
440 + (int)calcVerticalMargin: (int)i_curItem lastItem: (int)i_lastItem
441 {
442     int i_margin;
443     switch( i_curItem )
444     {
445     case CONFIG_ITEM_STRING:
446     case CONFIG_ITEM_PASSWORD:
447         switch( i_lastItem )
448         {
449         case CONFIG_ITEM_STRING:
450         case CONFIG_ITEM_PASSWORD:
451             i_margin = 8;
452             break;
453         case CONFIG_ITEM_STRING_LIST:
454             i_margin = 7;
455             break;
456         case CONFIG_ITEM_LOADFILE:
457         case CONFIG_ITEM_SAVEFILE:
458             i_margin = 8;
459             break;
460         case CONFIG_ITEM_MODULE:
461             i_margin = 4;
462             break;
463         case CONFIG_ITEM_INTEGER:
464             i_margin = 7;
465             break;
466         case CONFIG_ITEM_RANGED_INTEGER:
467             i_margin = 5;
468             break;
469         case CONFIG_ITEM_BOOL:
470             i_margin = 7;
471             break;
472         case CONFIG_ITEM_KEY:
473             i_margin = 6;
474             break;
475         case CONFIG_ITEM_MODULE_LIST:
476             i_margin = 8;
477             break;
478         default:
479             i_margin = 20;
480             break;
481         }
482         break;
483     case CONFIG_ITEM_STRING_LIST:
484         switch( i_lastItem )
485         {
486         case CONFIG_ITEM_STRING:
487         case CONFIG_ITEM_PASSWORD:
488             i_margin = 8;
489             break;
490         case CONFIG_ITEM_STRING_LIST:
491             i_margin = 7;
492             break;
493         case CONFIG_ITEM_LOADFILE:
494         case CONFIG_ITEM_SAVEFILE:
495             i_margin = 6;
496             break;
497         case CONFIG_ITEM_MODULE:
498             i_margin = 4;
499             break;
500         case CONFIG_ITEM_INTEGER:
501             i_margin = 7;
502             break;
503         case CONFIG_ITEM_RANGED_INTEGER:
504             i_margin = 5;
505             break;
506         case CONFIG_ITEM_BOOL:
507             i_margin = 7;
508             break;
509         case CONFIG_ITEM_KEY:
510             i_margin = 6;
511             break;
512         case CONFIG_ITEM_MODULE_LIST:
513             i_margin = 8;
514             break;
515         default:
516             i_margin = 20;
517             break;
518         }
519         break;
520     case CONFIG_ITEM_LOADFILE:
521     case CONFIG_ITEM_SAVEFILE:
522         switch( i_lastItem )
523         {
524         case CONFIG_ITEM_STRING:
525         case CONFIG_ITEM_PASSWORD:
526             i_margin = 13;
527             break;
528         case CONFIG_ITEM_STRING_LIST:
529             i_margin = 10;
530             break;
531         case CONFIG_ITEM_LOADFILE:
532         case CONFIG_ITEM_SAVEFILE:
533             i_margin = 9;
534             break;
535         case CONFIG_ITEM_MODULE:
536             i_margin = 9;
537             break;
538         case CONFIG_ITEM_INTEGER:
539             i_margin = 10;
540             break;
541         case CONFIG_ITEM_RANGED_INTEGER:
542             i_margin = 8;
543             break;
544         case CONFIG_ITEM_BOOL:
545             i_margin = 10;
546             break;
547         case CONFIG_ITEM_KEY:
548             i_margin = 9;
549             break;
550         case CONFIG_ITEM_MODULE_LIST:
551             i_margin = 11;
552             break;
553         default:
554             i_margin = 23;
555             break;
556         }
557         break;
558     case CONFIG_ITEM_MODULE:
559         switch( i_lastItem )
560         {
561         case CONFIG_ITEM_STRING:
562         case CONFIG_ITEM_PASSWORD:
563             i_margin = 8;
564             break;
565         case CONFIG_ITEM_STRING_LIST:
566             i_margin = 7;
567             break;
568         case CONFIG_ITEM_LOADFILE:
569         case CONFIG_ITEM_SAVEFILE:
570             i_margin = 6;
571             break;
572         case CONFIG_ITEM_MODULE:
573             i_margin = 5;
574             break;
575         case CONFIG_ITEM_INTEGER:
576             i_margin = 7;
577             break;
578         case CONFIG_ITEM_RANGED_INTEGER:
579             i_margin = 6;
580             break;
581         case CONFIG_ITEM_BOOL:
582             i_margin = 8;
583             break;
584         case CONFIG_ITEM_KEY:
585             i_margin = 7;
586             break;
587         case CONFIG_ITEM_MODULE_LIST:
588             i_margin = 9;
589             break;
590         default:
591             i_margin = 20;
592             break;
593         }
594         break;
595     case CONFIG_ITEM_INTEGER:
596         switch( i_lastItem )
597         {
598         case CONFIG_ITEM_STRING:
599         case CONFIG_ITEM_PASSWORD:
600             i_margin = 8;
601             break;
602         case CONFIG_ITEM_STRING_LIST:
603             i_margin = 7;
604             break;
605         case CONFIG_ITEM_LOADFILE:
606         case CONFIG_ITEM_SAVEFILE:
607             i_margin = 6;
608             break;
609         case CONFIG_ITEM_MODULE:
610             i_margin = 4;
611             break;
612         case CONFIG_ITEM_INTEGER:
613             i_margin = 7;
614             break;
615         case CONFIG_ITEM_RANGED_INTEGER:
616             i_margin = 5;
617             break;
618         case CONFIG_ITEM_BOOL:
619             i_margin = 7;
620             break;
621         case CONFIG_ITEM_KEY:
622             i_margin = 6;
623             break;
624         case CONFIG_ITEM_MODULE_LIST:
625             i_margin = 8;
626             break;
627         default:
628             i_margin = 20;
629             break;
630         }
631         break;
632     case CONFIG_ITEM_RANGED_INTEGER:
633         switch( i_lastItem )
634         {
635         case CONFIG_ITEM_STRING:
636         case CONFIG_ITEM_PASSWORD:
637             i_margin = 8;
638             break;
639         case CONFIG_ITEM_STRING_LIST:
640             i_margin = 7;
641             break;
642         case CONFIG_ITEM_LOADFILE:
643         case CONFIG_ITEM_SAVEFILE:
644             i_margin = 8;
645             break;
646         case CONFIG_ITEM_MODULE:
647             i_margin = 4;
648             break;
649         case CONFIG_ITEM_INTEGER:
650             i_margin = 7;
651             break;
652         case CONFIG_ITEM_RANGED_INTEGER:
653             i_margin = 5;
654             break;
655         case CONFIG_ITEM_BOOL:
656             i_margin = 7;
657             break;
658         case CONFIG_ITEM_KEY:
659             i_margin = 6;
660             break;
661         case CONFIG_ITEM_MODULE_LIST:
662             i_margin = 8;
663             break;
664         default:
665             i_margin = 20;
666             break;
667         }
668         break;
669     case CONFIG_ITEM_BOOL:
670         switch( i_lastItem )
671         {
672         case CONFIG_ITEM_STRING:
673         case CONFIG_ITEM_PASSWORD:
674             i_margin = 10;
675             break;
676         case CONFIG_ITEM_STRING_LIST:
677             i_margin = 9;
678             break;
679         case CONFIG_ITEM_LOADFILE:
680         case CONFIG_ITEM_SAVEFILE:
681             i_margin = 8;
682             break;
683         case CONFIG_ITEM_MODULE:
684             i_margin = 6;
685             break;
686         case CONFIG_ITEM_INTEGER:
687             i_margin = 9;
688             break;
689         case CONFIG_ITEM_RANGED_INTEGER:
690             i_margin = 7;
691             break;
692         case CONFIG_ITEM_BOOL:
693             i_margin = 7;
694             break;
695         case CONFIG_ITEM_KEY:
696             i_margin = 5;
697             break;
698         case CONFIG_ITEM_MODULE_LIST:
699             i_margin = 10;
700             break;
701         default:
702             i_margin = 20;
703             break;
704         }
705         break;
706     case CONFIG_ITEM_KEY:
707         switch( i_lastItem )
708         {
709         case CONFIG_ITEM_STRING:
710         case CONFIG_ITEM_PASSWORD:
711             i_margin = 8;
712             break;
713         case CONFIG_ITEM_STRING_LIST:
714             i_margin = 7;
715             break;
716         case CONFIG_ITEM_LOADFILE:
717         case CONFIG_ITEM_SAVEFILE:
718             i_margin = 6;
719             break;
720         case CONFIG_ITEM_MODULE:
721             i_margin = 6;
722             break;
723         case CONFIG_ITEM_INTEGER:
724             i_margin = 7;
725             break;
726         case CONFIG_ITEM_RANGED_INTEGER:
727             i_margin = 5;
728             break;
729         case CONFIG_ITEM_BOOL:
730             i_margin = 7;
731             break;
732         case CONFIG_ITEM_KEY:
733             i_margin = 8;
734             break;
735         case CONFIG_ITEM_MODULE_LIST:
736             i_margin = 10;
737             break;
738         default:
739             i_margin = 20;
740             break;
741         }
742         break;
743     case CONFIG_ITEM_MODULE_LIST:
744         switch( i_lastItem )
745         {
746         case CONFIG_ITEM_STRING:
747         case CONFIG_ITEM_PASSWORD:
748             i_margin = 10;
749             break;
750         case CONFIG_ITEM_STRING_LIST:
751             i_margin = 7;
752             break;
753         case CONFIG_ITEM_LOADFILE:
754         case CONFIG_ITEM_SAVEFILE:
755             i_margin = 6;
756             break;
757         case CONFIG_ITEM_MODULE:
758             i_margin = 6;
759             break;
760         case CONFIG_ITEM_INTEGER:
761             i_margin = 9;
762             break;
763         case CONFIG_ITEM_RANGED_INTEGER:
764             i_margin = 5;
765             break;
766         case CONFIG_ITEM_BOOL:
767             i_margin = 7;
768             break;
769         case CONFIG_ITEM_KEY:
770             i_margin = 5;
771             break;
772         case CONFIG_ITEM_MODULE_LIST:
773             i_margin = 8;
774             break;
775         default:
776             i_margin = 20;
777             break;
778         }
779         break;
780     default:
781         i_margin = 20;
782         break;
783     }
784     return i_margin;
785 }
786
787 + (VLCConfigControl *)newControl: (module_config_t *)_p_item
788                       withView: (NSView *)o_parent_view
789 {
790     VLCConfigControl *p_control = NULL;
791
792     switch( _p_item->i_type )
793     {
794     case CONFIG_ITEM_STRING:
795     case CONFIG_ITEM_PASSWORD:
796         if( !_p_item->i_list )
797         {
798             p_control = [[StringConfigControl alloc]
799                     initWithItem: _p_item
800                     withView: o_parent_view];
801         }
802         else
803         {
804             p_control = [[StringListConfigControl alloc]
805                     initWithItem: _p_item
806                     withView: o_parent_view];
807         }
808         break;
809     case CONFIG_ITEM_LOADFILE:
810     case CONFIG_ITEM_SAVEFILE:
811     case CONFIG_ITEM_DIRECTORY:
812         p_control = [[FileConfigControl alloc]
813                     initWithItem: _p_item
814                     withView: o_parent_view];
815         break;
816     case CONFIG_ITEM_MODULE:
817     case CONFIG_ITEM_MODULE_CAT:
818         p_control = [[ModuleConfigControl alloc]
819                     initWithItem: _p_item
820                     withView: o_parent_view];
821         break;
822     case CONFIG_ITEM_INTEGER:
823         if( _p_item->i_list )
824         {
825             p_control = [[IntegerListConfigControl alloc]
826                         initWithItem: _p_item
827                         withView: o_parent_view];
828         }
829         else if( (_p_item->min.i != 0 || _p_item->max.i != 0) && (_p_item->min.i != INT_MIN || _p_item->max.i != INT_MAX) )
830         {
831             p_control = [[RangedIntegerConfigControl alloc]
832                         initWithItem: _p_item
833                         withView: o_parent_view];
834         }
835         else
836         {
837             p_control = [[IntegerConfigControl alloc]
838                         initWithItem: _p_item
839                         withView: o_parent_view];
840         }
841         break;
842     case CONFIG_ITEM_BOOL:
843         p_control = [[BoolConfigControl alloc]
844                     initWithItem: _p_item
845                     withView: o_parent_view];
846         break;
847     case CONFIG_ITEM_FLOAT:
848         if( (_p_item->min.i != 0 || _p_item->max.i != 0) && (_p_item->min.i != INT_MIN || _p_item->max.i != INT_MAX) )
849         {
850             p_control = [[RangedFloatConfigControl alloc]
851                         initWithItem: _p_item
852                         withView: o_parent_view];
853         }
854         else
855         {
856             p_control = [[FloatConfigControl alloc]
857                         initWithItem: _p_item
858                         withView: o_parent_view];
859         }
860         break;
861     /* don't display keys in the advanced settings, since the current controls 
862     are broken by design. The user is required to change hotkeys in the sprefs
863     and can only change really advanced stuff here..
864     case CONFIG_ITEM_KEY:
865         p_control = [[KeyConfigControl alloc]
866                         initWithItem: _p_item
867                         withView: o_parent_view];
868         break; */
869     case CONFIG_ITEM_MODULE_LIST:
870     case CONFIG_ITEM_MODULE_LIST_CAT:
871         p_control = [[ModuleListConfigControl alloc]
872                     initWithItem: _p_item
873                     withView: o_parent_view];
874         break;
875     default:
876         break;
877     }
878     return p_control;
879 }
880
881 - (NSString *)name
882 {
883     return [[VLCMain sharedInstance] localizedString: psz_name];
884 }
885
886 - (int)type
887 {
888     return i_type;
889 }
890
891 - (int)viewType
892 {
893     return i_view_type;
894 }
895
896 - (BOOL)isAdvanced
897 {
898     return b_advanced;
899 }
900
901 - (int)intValue
902 {
903     return 0;
904 }
905
906 - (float)floatValue
907 {
908     return 0;
909 }
910
911 - (char *)stringValue
912 {
913     return NULL;
914 }
915
916 - (void)applyChanges
917 {
918     vlc_value_t val;
919     switch( p_item->i_type )
920     {
921     case CONFIG_ITEM_STRING:
922     case CONFIG_ITEM_PASSWORD:
923     case CONFIG_ITEM_LOADFILE:
924     case CONFIG_ITEM_SAVEFILE:
925     case CONFIG_ITEM_DIRECTORY:
926     case CONFIG_ITEM_MODULE:
927     case CONFIG_ITEM_MODULE_LIST:
928     case CONFIG_ITEM_MODULE_LIST_CAT:
929         config_PutPsz( VLCIntf, psz_name, [self stringValue] );
930         break;
931     case CONFIG_ITEM_KEY:
932         /* So you don't need to restart to have the changes take effect */
933         val.i_int = [self intValue];
934         var_Set( VLCIntf->p_libvlc, psz_name, val );
935     case CONFIG_ITEM_INTEGER:
936     case CONFIG_ITEM_BOOL:
937         config_PutInt( VLCIntf, psz_name, [self intValue] );
938         break;
939     case CONFIG_ITEM_FLOAT:
940         config_PutFloat( VLCIntf, psz_name, [self floatValue] );
941         break;
942     }
943 }
944
945 - (void)resetValues
946 {
947 }
948
949 - (int)labelSize
950 {
951     return [o_label frame].size.width;
952 }
953
954 - (void) alignWithXPosition:(int)i_xPos;
955 {
956     /* FIXME: not implemented atm, but created to shut up the warning
957      * about "method definition not found" -- FK @ 7/24/05 */
958 }
959 @end
960
961 @implementation StringConfigControl
962 - (id) initWithItem: (module_config_t *)_p_item
963            withView: (NSView *)o_parent_view
964 {
965     NSRect mainFrame = [o_parent_view frame];
966     NSString *o_labelString, *o_textfieldString, *o_textfieldTooltip;
967     mainFrame.size.height = 22;
968     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
969     mainFrame.origin.x = LEFTMARGIN;
970     mainFrame.origin.y = 0;
971
972     if( [super initWithFrame: mainFrame item: _p_item] != nil )
973     {
974         if( p_item->i_type == CONFIG_ITEM_PASSWORD )
975             i_view_type = CONFIG_ITEM_PASSWORD;
976         else
977             i_view_type = CONFIG_ITEM_STRING;
978
979         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
980                               [[VLCMain sharedInstance] localizedString: (char *)p_item->psz_longtext]
981                                                           toWidth: PREFS_WRAP];
982
983         /* add the label */
984         if( p_item->psz_text )
985             o_labelString = [[VLCMain sharedInstance]
986                                 localizedString: (char *)p_item->psz_text];
987         else
988             o_labelString = [NSString stringWithString:@""];
989         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString, o_textfieldTooltip )
990         [o_label setAutoresizingMask:NSViewNotSizable ];
991         [self addSubview: o_label];
992
993         /* build the textfield */
994         if( p_item->value.psz )
995             o_textfieldString = [[VLCMain sharedInstance]
996                                     localizedString: (char *)p_item->value.psz];
997         else
998             o_textfieldString = [NSString stringWithString: @""];
999         if( p_item->i_type == CONFIG_ITEM_PASSWORD )
1000         {
1001             ADD_SECURETEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
1002                           0, mainFrame.size.width - [o_label frame].size.width -
1003                           2, o_textfieldTooltip, o_textfieldString )
1004         }
1005         else
1006         {
1007             ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
1008                             0, mainFrame.size.width - [o_label frame].size.width -
1009                             2, o_textfieldTooltip, o_textfieldString )
1010         }
1011         [o_textfield setAutoresizingMask:NSViewWidthSizable ];
1012
1013         [self addSubview: o_textfield];
1014     }
1015     return self;
1016 }
1017
1018 - (void) alignWithXPosition:(int)i_xPos
1019 {
1020     NSRect frame;
1021     NSRect superFrame = [self frame];
1022     frame = [o_label frame];
1023     frame.origin.x = i_xPos - frame.size.width - 3;
1024     [o_label setFrame:frame];
1025
1026     frame = [o_textfield frame];
1027     frame.origin.x = i_xPos + 2;
1028     frame.size.width = superFrame.size.width - frame.origin.x - 1;
1029     [o_textfield setFrame:frame];
1030 }
1031
1032 - (void)dealloc
1033 {
1034     [o_textfield release];
1035     [super dealloc];
1036 }
1037
1038 - (char *)stringValue
1039 {
1040     return [[VLCMain sharedInstance] delocalizeString:
1041                         [o_textfield stringValue]];
1042 }
1043
1044 - (void)resetValues
1045 {
1046     NSString *o_textfieldString;
1047     char *psz_value = config_GetPsz( VLCIntf, p_item->psz_name );
1048     if( psz_value )
1049         o_textfieldString = [[VLCMain sharedInstance]
1050                                 localizedString: psz_value];
1051     else
1052         o_textfieldString = [NSString stringWithString: @""];
1053     free( psz_value );
1054     [super resetValues];
1055 }
1056 @end
1057
1058 @implementation StringListConfigControl
1059 - (id) initWithItem: (module_config_t *)_p_item
1060            withView: (NSView *)o_parent_view
1061 {
1062     NSRect mainFrame = [o_parent_view frame];
1063     NSString *o_labelString, *o_textfieldTooltip;
1064     mainFrame.size.height = 22;
1065     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1066     mainFrame.origin.x = LEFTMARGIN;
1067     mainFrame.origin.y = 0;
1068
1069     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1070     {
1071         int i_index;
1072         i_view_type = CONFIG_ITEM_STRING_LIST;
1073
1074         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
1075                               [[VLCMain sharedInstance]
1076                                localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1077
1078         /* add the label */
1079         if( p_item->psz_text )
1080             o_labelString = [[VLCMain sharedInstance]
1081                                 localizedString: (char *)p_item->psz_text];
1082         else
1083             o_labelString = [NSString stringWithString:@""];
1084         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString, o_textfieldTooltip )
1085         [o_label setAutoresizingMask:NSViewNotSizable ];
1086         [self addSubview: o_label];
1087
1088         /* build the textfield */
1089         ADD_COMBO( o_combo, mainFrame, [o_label frame].size.width,
1090             -2, 0, o_textfieldTooltip )
1091         [o_combo setAutoresizingMask:NSViewWidthSizable ];
1092         for( i_index = 0; i_index < p_item->i_list; i_index++ )
1093         {
1094             if( !p_item->value.psz && !p_item->ppsz_list[i_index] )
1095                 [o_combo selectItemAtIndex: i_index];
1096             else if( p_item->value.psz && p_item->ppsz_list[i_index] &&
1097                 !strcmp( p_item->value.psz, p_item->ppsz_list[i_index] ) )
1098                 [o_combo selectItemAtIndex: i_index];
1099        }
1100         [self addSubview: o_combo];
1101     }
1102     return self;
1103 }
1104
1105 - (void) alignWithXPosition:(int)i_xPos
1106 {
1107     NSRect frame;
1108     NSRect superFrame = [self frame];
1109     frame = [o_label frame];
1110     frame.origin.x = i_xPos - frame.size.width - 3;
1111     [o_label setFrame:frame];
1112
1113     frame = [o_combo frame];
1114     frame.origin.x = i_xPos + 2;
1115     frame.size.width = superFrame.size.width - frame.origin.x + 2;
1116     [o_combo setFrame:frame];
1117 }
1118
1119 - (void)dealloc
1120 {
1121     [o_combo release];
1122     [super dealloc];
1123 }
1124
1125 - (char *)stringValue
1126 {
1127     if( [o_combo indexOfSelectedItem] >= 0 ) {
1128         if( p_item->ppsz_list[[o_combo indexOfSelectedItem]] != NULL )
1129             return strdup( p_item->ppsz_list[[o_combo indexOfSelectedItem]] );
1130     } else {
1131         if( [[VLCMain sharedInstance] delocalizeString: [o_combo stringValue]] != NULL )
1132             return strdup( [[VLCMain sharedInstance] delocalizeString: [o_combo stringValue]] );
1133     }
1134     return NULL;
1135 }
1136
1137 - (void)resetValues
1138 {
1139     int i_index;
1140     [o_combo reloadData];
1141     char *psz_value = config_GetPsz( VLCIntf, p_item->psz_name );
1142
1143     for( i_index = 0; i_index < p_item->i_list; i_index++ )
1144     {
1145         if( !psz_value && !p_item->ppsz_list[i_index] )
1146             [o_combo selectItemAtIndex: i_index];
1147         else if( psz_value && p_item->ppsz_list[i_index] &&
1148             !strcmp( psz_value, p_item->ppsz_list[i_index] ) )
1149             [o_combo selectItemAtIndex: i_index];
1150     }
1151
1152     free( psz_value );
1153     [super resetValues];
1154 }
1155 @end
1156
1157 @implementation StringListConfigControl (NSComboBoxDataSource)
1158 - (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox
1159 {
1160         return p_item->i_list;
1161 }
1162
1163 - (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)i_index
1164 {
1165     if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
1166     {
1167         return [[VLCMain sharedInstance]
1168                     localizedString: (char *)p_item->ppsz_list_text[i_index]];
1169     } else return [[VLCMain sharedInstance]
1170                     localizedString: (char *)p_item->ppsz_list[i_index]];
1171 }
1172 @end
1173
1174 @implementation FileConfigControl
1175 - (id) initWithItem: (module_config_t *)_p_item
1176            withView: (NSView *)o_parent_view
1177 {
1178     NSRect mainFrame = [o_parent_view frame];
1179     NSString *o_labelString, *o_itemTooltip, *o_textfieldString;
1180     mainFrame.size.height = 46;
1181     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1182     mainFrame.origin.x = LEFTMARGIN;
1183     mainFrame.origin.y = 0;
1184
1185     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1186     {
1187         i_view_type = CONFIG_ITEM_LOADFILE;
1188
1189         o_itemTooltip = [[VLCMain sharedInstance]
1190                            wrapString: [[VLCMain sharedInstance]
1191                                         localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1192
1193         /* is it a directory */
1194         b_directory = ( [self type] == CONFIG_ITEM_DIRECTORY ) ? YES : NO;
1195
1196         /* add the label */
1197         if( p_item->psz_text )
1198             o_labelString = [[VLCMain sharedInstance]
1199                                 localizedString: (char *)p_item->psz_text];
1200         else
1201             o_labelString = [NSString stringWithString:@""];
1202         ADD_LABEL( o_label, mainFrame, 0, 3, o_labelString, o_itemTooltip )
1203         [o_label setAutoresizingMask:NSViewNotSizable ];
1204         [self addSubview: o_label];
1205
1206         /* build the button */
1207         ADD_RIGHT_BUTTON( o_button, mainFrame, 0, 0, o_itemTooltip,
1208                             _NS("Browse...") )
1209         [o_button setAutoresizingMask:NSViewMinXMargin ];
1210         [self addSubview: o_button];
1211
1212         /* build the textfield */
1213         if( p_item->value.psz )
1214             o_textfieldString = [NSString stringWithFormat: @"%s", (char *)p_item->value.psz];
1215         else
1216             o_textfieldString = [NSString stringWithString: @""];
1217         ADD_TEXTFIELD( o_textfield, mainFrame, 12, 2, mainFrame.size.width -
1218                         8 - [o_button frame].size.width,
1219                         o_itemTooltip, o_textfieldString )
1220         [o_textfield setAutoresizingMask:NSViewWidthSizable ];
1221         [self addSubview: o_textfield];
1222     }
1223     return self;
1224 }
1225
1226 - (void) alignWithXPosition:(int)i_xPos
1227 {
1228     ;
1229 }
1230
1231 - (void)dealloc
1232 {
1233     [o_textfield release];
1234     [o_button release];
1235     [super dealloc];
1236 }
1237
1238 - (IBAction)openFileDialog: (id)sender
1239 {
1240     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
1241
1242     [o_open_panel setTitle: (b_directory)?
1243         _NS("Select a directory"):_NS("Select a file")];
1244     [o_open_panel setPrompt: _NS("Select")];
1245     [o_open_panel setAllowsMultipleSelection: NO];
1246     [o_open_panel setCanChooseFiles: !b_directory];
1247     [o_open_panel setCanChooseDirectories: b_directory];
1248     [o_open_panel beginSheetForDirectory:nil
1249         file:nil
1250         types:nil
1251         modalForWindow:[sender window]
1252         modalDelegate: self
1253         didEndSelector: @selector(pathChosenInPanel:
1254                         withReturn:
1255                         contextInfo:)
1256         contextInfo: nil];
1257 }
1258
1259 - (void)pathChosenInPanel:(NSOpenPanel *)o_sheet
1260     withReturn:(int)i_return_code contextInfo:(void  *)o_context_info
1261 {
1262     if( i_return_code == NSOKButton )
1263     {
1264         NSString *o_path = [[[o_sheet URLs] objectAtIndex: 0] path];
1265         [o_textfield setStringValue: o_path];
1266     }
1267 }
1268
1269 - (char *)stringValue
1270 {
1271     if( [[o_textfield stringValue] length] != 0)
1272         return strdup( [[o_textfield stringValue] fileSystemRepresentation] );
1273     else
1274         return NULL;
1275 }
1276
1277 -(void)resetValues
1278 {
1279     NSString *o_textfieldString;
1280     char *psz_value = config_GetPsz( VLCIntf, p_item->psz_name );
1281     if( psz_value )
1282         o_textfieldString = [NSString stringWithFormat: @"%s", psz_value];
1283     else
1284         o_textfieldString = [NSString stringWithString: @""];
1285
1286     free(psz_value);
1287     [super resetValues];
1288 }
1289 @end
1290
1291 @implementation ModuleConfigControl
1292 - (id) initWithItem: (module_config_t *)_p_item
1293            withView: (NSView *)o_parent_view
1294 {
1295     NSRect mainFrame = [o_parent_view frame];
1296     NSString *o_labelString, *o_popupTooltip;
1297     mainFrame.size.height = 22;
1298     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1299     mainFrame.origin.x = LEFTMARGIN;
1300     mainFrame.origin.y = 0;
1301
1302     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1303     {
1304         i_view_type = CONFIG_ITEM_MODULE;
1305
1306         o_popupTooltip = [[VLCMain sharedInstance] wrapString:
1307                           [[VLCMain sharedInstance]
1308                            localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1309
1310         /* add the label */
1311         if( p_item->psz_text )
1312             o_labelString = [[VLCMain sharedInstance]
1313                                 localizedString: (char *)p_item->psz_text];
1314         else
1315             o_labelString = [NSString stringWithString:@""];
1316         ADD_LABEL( o_label, mainFrame, 0, -1, o_labelString, o_popupTooltip )
1317         [o_label setAutoresizingMask:NSViewNotSizable ];
1318         [self addSubview: o_label];
1319
1320         /* build the popup */
1321         ADD_POPUP( o_popup, mainFrame, [o_label frame].size.width,
1322             -2, 0, o_popupTooltip )
1323         [o_popup setAutoresizingMask:NSViewWidthSizable ];
1324         [o_popup addItemWithTitle: _NS("Default")];
1325         [[o_popup lastItem] setTag: -1];
1326         [o_popup selectItem: [o_popup lastItem]];
1327
1328         [self resetValues];
1329         [self addSubview: o_popup];
1330     }
1331     return self;
1332 }
1333
1334 - (void) alignWithXPosition:(int)i_xPos
1335 {
1336     NSRect frame;
1337     NSRect superFrame = [self frame];
1338     frame = [o_label frame];
1339     frame.origin.x = i_xPos - frame.size.width - 3;
1340     [o_label setFrame:frame];
1341
1342     frame = [o_popup frame];
1343     frame.origin.x = i_xPos - 1;
1344     frame.size.width = superFrame.size.width - frame.origin.x + 2;
1345     [o_popup setFrame:frame];
1346 }
1347
1348 - (void)dealloc
1349 {
1350     [o_popup release];
1351     [super dealloc];
1352 }
1353
1354 - (char *)stringValue
1355 {
1356     NSString *newval = [o_popup titleOfSelectedItem];
1357     char *returnval = NULL;
1358     size_t i_module_index;
1359     module_t *p_parser, **p_list;
1360
1361     p_list = module_list_get( NULL );
1362     for( i_module_index = 0; p_list[i_module_index]; i_module_index++ )
1363     {
1364         p_parser = p_list[i_module_index];
1365
1366         if( p_item->i_type == CONFIG_ITEM_MODULE )
1367         {
1368             if( module_provides( p_parser, p_item->psz_type ) )
1369             {
1370                 NSString *o_description = [[VLCMain sharedInstance]
1371                     localizedString: module_get_name( p_parser, TRUE )];
1372                 if( [newval isEqualToString: o_description] )
1373                 {
1374                     returnval = strdup( module_get_object( p_parser ));
1375                     break;
1376                 }
1377             }
1378         }
1379         else
1380         {
1381             int i;
1382
1383             if( module_is_main( p_parser) )
1384                 continue;
1385             unsigned int confsize, unused;
1386             module_config_t *p_config = module_config_get( p_parser, &confsize );
1387             for ( i = 0; i < confsize; i++ )
1388             {
1389                 module_config_t *p_item = p_config + i;
1390                 /* Hack: required subcategory is stored in i_min */
1391                 if( p_item->i_type == CONFIG_SUBCATEGORY &&
1392                     p_item->value.i == p_item->min.i )
1393                 {
1394                     NSString *o_description = [[VLCMain sharedInstance]
1395                         localizedString: module_get_name( p_parser, TRUE )];
1396                     if( [newval isEqualToString: o_description] )
1397                     {
1398                         returnval = strdup(module_get_object( p_parser ));
1399                         break;
1400                     }
1401                 }
1402             }
1403             module_config_free( p_config );
1404         }
1405     }
1406     module_list_free( p_list );
1407     return returnval;
1408 }
1409
1410 -(void)resetValues
1411 {
1412     /* build a list of available modules */
1413     size_t i_index;
1414     module_t *p_parser, **p_list;
1415
1416     p_list = module_list_get( NULL );
1417     for( i_index = 0; p_list[i_index]; i_index++ )
1418     {
1419         p_parser = p_list[i_index];
1420
1421         if( p_item->i_type == CONFIG_ITEM_MODULE )
1422         {
1423             if( module_provides( p_parser, p_item->psz_type ) )
1424             {
1425                 NSString *o_description = [[VLCMain sharedInstance]
1426                     localizedString: module_get_name( p_parser, TRUE )];
1427                 [o_popup addItemWithTitle: o_description];
1428                 char *psz_value = config_GetPsz( VLCIntf, p_item->psz_name );
1429
1430                 if( psz_value &&
1431                     !strcmp( psz_value, module_get_object( p_parser ) ) )
1432                     [o_popup selectItem:[o_popup lastItem]];
1433
1434                 free(psz_value);
1435             }
1436         }
1437         else
1438         {
1439             int i;
1440
1441             if( module_is_main( p_parser ) )
1442                 continue;
1443             unsigned int confsize;
1444             unsigned int unused;
1445             module_config_t *p_configlist = module_config_get( p_parser, &confsize );
1446             for ( i = 0; i < confsize; i++ )
1447             {
1448                 module_config_t *p_config = &p_configlist[i];
1449                 /* Hack: required subcategory is stored in i_min */
1450                 if( p_config->i_type == CONFIG_SUBCATEGORY &&
1451                     config_GetInt( VLCIntf, p_item->psz_name) == p_item->min.i )
1452                 {
1453                     NSString *o_description = [[VLCMain sharedInstance]
1454                         localizedString: module_get_name( p_parser, TRUE )];
1455                     [o_popup addItemWithTitle: o_description];
1456                     char *psz_value = config_GetPsz( VLCIntf, p_item->psz_name );
1457
1458                     if( psz_value && !strcmp(psz_value,
1459                                             module_get_object( p_parser )) )
1460                         [o_popup selectItem:[o_popup lastItem]];
1461
1462                     free( psz_value );
1463                 }
1464             }
1465             module_config_free( p_configlist );
1466         }
1467     }
1468     module_list_free( p_list );
1469     [super resetValues];
1470 }
1471 @end
1472
1473 @implementation IntegerConfigControl
1474 - (id) initWithItem: (module_config_t *)_p_item
1475            withView: (NSView *)o_parent_view
1476 {
1477     NSRect mainFrame = [o_parent_view frame];
1478     NSString *o_labelString, *o_tooltip;
1479     mainFrame.size.height = 23;
1480     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1481     mainFrame.origin.x = LEFTMARGIN;
1482     mainFrame.origin.y = 0;
1483
1484     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1485     {
1486         i_view_type = CONFIG_ITEM_INTEGER;
1487
1488         o_tooltip = [[VLCMain sharedInstance] wrapString:
1489             [[VLCMain sharedInstance]
1490                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1491
1492         /* add the label */
1493         if( p_item->psz_text )
1494             o_labelString = [[VLCMain sharedInstance]
1495                                 localizedString: (char *)p_item->psz_text];
1496         else
1497             o_labelString = [NSString stringWithString:@""];
1498         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString, o_tooltip )
1499         [o_label setAutoresizingMask:NSViewNotSizable ];
1500         [self addSubview: o_label];
1501
1502         /* build the stepper */
1503         ADD_STEPPER( o_stepper, mainFrame, mainFrame.size.width - 19,
1504             0, o_tooltip, -100000, 100000)
1505         [o_stepper setIntValue: p_item->value.i];
1506         [o_stepper setAutoresizingMask:NSViewMaxXMargin ];
1507         [self addSubview: o_stepper];
1508
1509         ADD_TEXTFIELD( o_textfield, mainFrame, mainFrame.size.width - 19 - 52,
1510             1, 49, o_tooltip, @"" )
1511         [o_textfield setIntValue: p_item->value.i];
1512         [o_textfield setDelegate: self];
1513         [[NSNotificationCenter defaultCenter] addObserver: self
1514             selector: @selector(textfieldChanged:)
1515             name: NSControlTextDidChangeNotification
1516             object: o_textfield];
1517         [o_textfield setAutoresizingMask:NSViewMaxXMargin ];
1518         [self addSubview: o_textfield];
1519     }
1520     return self;
1521 }
1522
1523 - (void) alignWithXPosition:(int)i_xPos
1524 {
1525     NSRect frame;
1526     frame = [o_label frame];
1527     frame.origin.x = i_xPos - frame.size.width - 3;
1528     [o_label setFrame:frame];
1529
1530     frame = [o_textfield frame];
1531     frame.origin.x = i_xPos + 2;
1532     [o_textfield setFrame:frame];
1533
1534     frame = [o_stepper frame];
1535     frame.origin.x = i_xPos + [o_textfield frame].size.width + 5;
1536     [o_stepper setFrame:frame];
1537 }
1538
1539 - (void)dealloc
1540 {
1541     [o_stepper release];
1542     [o_textfield release];
1543     [super dealloc];
1544 }
1545
1546 - (IBAction)stepperChanged:(id)sender
1547 {
1548     [o_textfield setIntValue: [o_stepper intValue]];
1549 }
1550
1551 - (void)textfieldChanged:(NSNotification *)o_notification
1552 {
1553     [o_stepper setIntValue: [o_textfield intValue]];
1554 }
1555
1556 - (int)intValue
1557 {
1558     return [o_textfield intValue];
1559 }
1560
1561 -(void)resetValues
1562 {
1563     [o_textfield setIntValue: config_GetInt(VLCIntf, p_item->psz_name)];
1564     [super resetValues];
1565 }
1566
1567 @end
1568
1569 @implementation IntegerListConfigControl
1570
1571 - (id) initWithItem: (module_config_t *)_p_item
1572            withView: (NSView *)o_parent_view
1573 {
1574     NSRect mainFrame = [o_parent_view frame];
1575     NSString *o_labelString, *o_textfieldTooltip;
1576     mainFrame.size.height = 22;
1577     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1578     mainFrame.origin.x = LEFTMARGIN;
1579     mainFrame.origin.y = 0;
1580
1581     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1582     {
1583         int i_index;
1584         i_view_type = CONFIG_ITEM_STRING_LIST;
1585
1586         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
1587                               [[VLCMain sharedInstance]
1588                                localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];        
1589
1590         /* add the label */
1591         if( p_item->psz_text )
1592             o_labelString = [[VLCMain sharedInstance]
1593                 localizedString: (char *)p_item->psz_text];
1594         else
1595             o_labelString = [NSString stringWithString:@""];
1596         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString, o_textfieldTooltip )
1597         [o_label setAutoresizingMask:NSViewNotSizable ];
1598         [self addSubview: o_label];
1599
1600         /* build the textfield */
1601         ADD_COMBO( o_combo, mainFrame, [o_label frame].size.width,
1602             -2, 0, o_textfieldTooltip )
1603         [o_combo setAutoresizingMask:NSViewWidthSizable ];
1604         for( i_index = 0; i_index < p_item->i_list; i_index++ )
1605         {
1606             if( p_item->value.i == p_item->pi_list[i_index] )
1607             {
1608                 [o_combo selectItemAtIndex: i_index];
1609             }
1610         }
1611         [self addSubview: o_combo];
1612     }
1613     return self;
1614 }
1615
1616 - (void) alignWithXPosition:(int)i_xPos
1617 {
1618     NSRect frame;
1619     NSRect superFrame = [self frame];
1620     frame = [o_label frame];
1621     frame.origin.x = i_xPos - frame.size.width - 3;
1622     [o_label setFrame:frame];
1623
1624     frame = [o_combo frame];
1625     frame.origin.x = i_xPos + 2;
1626     frame.size.width = superFrame.size.width - frame.origin.x + 2;
1627     [o_combo setFrame:frame];
1628 }
1629
1630 - (void)dealloc
1631 {
1632     [o_combo release];
1633     [super dealloc];
1634 }
1635
1636 - (int)intValue
1637 {
1638     if( [o_combo indexOfSelectedItem] >= 0 )
1639         return p_item->pi_list[[o_combo indexOfSelectedItem]];
1640     else
1641         return [o_combo intValue];
1642 }
1643
1644 -(void)resetValues
1645 {
1646     int i_index;
1647     [o_combo reloadData];
1648     for( i_index = 0; i_index < p_item->i_list; i_index++ )
1649     {
1650         if( config_GetInt( VLCIntf, p_item->psz_name) == p_item->pi_list[i_index] )
1651         {
1652             [o_combo selectItemAtIndex: i_index];
1653         }
1654     }
1655
1656 }
1657 @end
1658
1659 @implementation IntegerListConfigControl (NSComboBoxDataSource)
1660 - (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox
1661 {
1662     return p_item->i_list;
1663 }
1664
1665 - (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)i_index
1666 {
1667     if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
1668         return [[VLCMain sharedInstance]
1669                     localizedString: (char *)p_item->ppsz_list_text[i_index]];
1670     else
1671         return [NSString stringWithFormat: @"%i", p_item->pi_list[i_index]];
1672 }
1673 @end
1674
1675 @implementation RangedIntegerConfigControl
1676 - (id) initWithItem: (module_config_t *)_p_item
1677            withView: (NSView *)o_parent_view
1678 {
1679     NSRect mainFrame = [o_parent_view frame];
1680     NSString *o_labelString, *o_tooltip;
1681     mainFrame.size.height = 50;
1682     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1683     mainFrame.origin.x = LEFTMARGIN;
1684     mainFrame.origin.y = 0;
1685
1686     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1687     {
1688         i_view_type = CONFIG_ITEM_RANGED_INTEGER;
1689
1690         o_tooltip = [[VLCMain sharedInstance] wrapString:
1691                      [[VLCMain sharedInstance]
1692                       localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1693
1694         /* add the label */
1695         if( p_item->psz_text )
1696             o_labelString = [[VLCMain sharedInstance]
1697                                 localizedString: (char *)p_item->psz_text];
1698         else
1699             o_labelString = [NSString stringWithString:@""];
1700         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString, o_tooltip )
1701         [o_label setAutoresizingMask:NSViewNotSizable ];
1702         [self addSubview: o_label];
1703
1704         /* build the textfield */
1705         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
1706             28, 49, o_tooltip, @"" )
1707         [o_textfield setIntValue: p_item->value.i];
1708         [o_textfield setAutoresizingMask:NSViewMaxXMargin ];
1709         [o_textfield setDelegate: self];
1710         [[NSNotificationCenter defaultCenter] addObserver: self
1711             selector: @selector(textfieldChanged:)
1712             name: NSControlTextDidChangeNotification
1713             object: o_textfield];
1714         [self addSubview: o_textfield];
1715
1716         /* build the mintextfield */
1717         ADD_LABEL( o_textfield_min, mainFrame, 12, -30, @"-8888", @"" )
1718         [o_textfield_min setIntValue: p_item->min.i];
1719         [o_textfield_min setAutoresizingMask:NSViewMaxXMargin ];
1720         [o_textfield_min setAlignment:NSRightTextAlignment];
1721         [self addSubview: o_textfield_min];
1722
1723         /* build the maxtextfield */
1724         ADD_LABEL( o_textfield_max, mainFrame,
1725                     mainFrame.size.width - 31, -30, @"8888", @"" )
1726         [o_textfield_max setIntValue: p_item->max.i];
1727         [o_textfield_max setAutoresizingMask:NSViewMinXMargin ];
1728         [self addSubview: o_textfield_max];
1729
1730         /* build the slider */
1731         ADD_SLIDER( o_slider, mainFrame, [o_textfield_min frame].origin.x +
1732             [o_textfield_min frame].size.width + 6, -1, mainFrame.size.width -
1733             [o_textfield_max frame].size.width -
1734             [o_textfield_max frame].size.width - 14 -
1735             [o_textfield_min frame].origin.x, o_tooltip,
1736             p_item->min.i, p_item->max.i )
1737         [o_slider setIntValue: p_item->value.i];
1738         [o_slider setAutoresizingMask:NSViewWidthSizable ];
1739         [o_slider setTarget: self];
1740         [o_slider setAction: @selector(sliderChanged:)];
1741         [o_slider sendActionOn:NSLeftMouseUpMask | NSLeftMouseDownMask |
1742             NSLeftMouseDraggedMask];
1743         [self addSubview: o_slider];
1744
1745     }
1746     return self;
1747 }
1748
1749 - (void) alignWithXPosition:(int)i_xPos
1750 {
1751     NSRect frame;
1752     frame = [o_label frame];
1753     frame.origin.x = i_xPos - frame.size.width - 3;
1754     [o_label setFrame:frame];
1755
1756     frame = [o_textfield frame];
1757     frame.origin.x = i_xPos + 2;
1758     [o_textfield setFrame:frame];
1759 }
1760
1761 - (void)dealloc
1762 {
1763     [o_textfield release];
1764     [o_textfield_min release];
1765     [o_textfield_max release];
1766     [o_slider release];
1767     [super dealloc];
1768 }
1769
1770 - (IBAction)sliderChanged:(id)sender
1771 {
1772     [o_textfield setIntValue: [o_slider intValue]];
1773 }
1774
1775 - (void)textfieldChanged:(NSNotification *)o_notification
1776 {
1777     [o_slider setIntValue: [o_textfield intValue]];
1778 }
1779
1780 - (int)intValue
1781 {
1782     return [o_slider intValue];
1783 }
1784
1785 - (void)resetValues
1786 {
1787     int value = config_GetInt( VLCIntf, p_item->psz_name );
1788     [o_textfield setIntValue:value];
1789     [o_slider setIntValue:value];
1790     [super resetValues];
1791 }
1792 @end
1793
1794 @implementation FloatConfigControl
1795 - (id) initWithItem: (module_config_t *)_p_item
1796            withView: (NSView *)o_parent_view
1797 {
1798     NSRect mainFrame = [o_parent_view frame];
1799     NSString *o_labelString, *o_tooltip;
1800     mainFrame.size.height = 23;
1801     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1802     mainFrame.origin.x = LEFTMARGIN;
1803     mainFrame.origin.y = 0;
1804
1805     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1806     {
1807         i_view_type = CONFIG_ITEM_INTEGER;
1808
1809         o_tooltip = [[VLCMain sharedInstance] wrapString:
1810             [[VLCMain sharedInstance]
1811                 localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
1812
1813         /* add the label */
1814         if( p_item->psz_text )
1815             o_labelString = [[VLCMain sharedInstance]
1816                                 localizedString: (char *)p_item->psz_text];
1817         else
1818             o_labelString = [NSString stringWithString:@""];
1819         ADD_LABEL( o_label, mainFrame, 0, -2, o_labelString, o_tooltip )
1820         [o_label setAutoresizingMask:NSViewNotSizable ];
1821         [self addSubview: o_label];
1822
1823         /* build the stepper */
1824         ADD_STEPPER( o_stepper, mainFrame, mainFrame.size.width - 19,
1825             0, o_tooltip, -100000, 100000)
1826         [o_stepper setFloatValue: p_item->value.f];
1827         [o_stepper setAutoresizingMask:NSViewMaxXMargin ];
1828         [self addSubview: o_stepper];
1829
1830         /* build the textfield */
1831         ADD_TEXTFIELD( o_textfield, mainFrame, mainFrame.size.width - 19 - 52,
1832             1, 49, o_tooltip, @"" )
1833         [o_textfield setFloatValue: p_item->value.f];
1834         [o_textfield setDelegate: self];
1835         [[NSNotificationCenter defaultCenter] addObserver: self
1836             selector: @selector(textfieldChanged:)
1837             name: NSControlTextDidChangeNotification
1838             object: o_textfield];
1839         [o_textfield setAutoresizingMask:NSViewMaxXMargin ];
1840         [self addSubview: o_textfield];
1841     }
1842     return self;
1843 }
1844
1845 - (void) alignWithXPosition:(int)i_xPos
1846 {
1847     NSRect frame;
1848     frame = [o_label frame];
1849     frame.origin.x = i_xPos - frame.size.width - 3;
1850     [o_label setFrame:frame];
1851
1852     frame = [o_textfield frame];
1853     frame.origin.x = i_xPos + 2;
1854     [o_textfield setFrame:frame];
1855
1856     frame = [o_stepper frame];
1857     frame.origin.x = i_xPos + [o_textfield frame].size.width + 5;
1858     [o_stepper setFrame:frame];
1859 }
1860
1861 - (void)dealloc
1862 {
1863     [o_stepper release];
1864     [o_textfield release];
1865     [super dealloc];
1866 }
1867
1868 - (IBAction)stepperChanged:(id)sender
1869 {
1870     [o_textfield setFloatValue: [o_stepper floatValue]];
1871 }
1872
1873 - (void)textfieldChanged:(NSNotification *)o_notification
1874 {
1875     [o_stepper setFloatValue: [o_textfield floatValue]];
1876 }
1877
1878 - (float)floatValue
1879 {
1880     return [o_stepper floatValue];
1881 }
1882
1883 - (void)resetValues
1884 {
1885     [o_textfield setFloatValue: config_GetFloat( VLCIntf, p_item->psz_name)];
1886     [super resetValues];
1887 }
1888 @end
1889
1890 @implementation RangedFloatConfigControl
1891 - (id) initWithItem: (module_config_t *)_p_item
1892            withView: (NSView *)o_parent_view
1893 {
1894     NSRect mainFrame = [o_parent_view frame];
1895     NSString *o_labelString, *o_tooltip;
1896     mainFrame.size.height = 50;
1897     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1898     mainFrame.origin.x = LEFTMARGIN;
1899     mainFrame.origin.y = 0;
1900
1901     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1902     {
1903         i_view_type = CONFIG_ITEM_RANGED_INTEGER;
1904
1905         o_tooltip = [[VLCMain sharedInstance] wrapString:
1906                      [[VLCMain sharedInstance]
1907                       localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];        
1908
1909         /* add the label */
1910         if( p_item->psz_text )
1911             o_labelString = [[VLCMain sharedInstance]
1912                                 localizedString: (char *)p_item->psz_text];
1913         else
1914             o_labelString = [NSString stringWithString:@""];
1915         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString, o_tooltip )
1916         [o_label setAutoresizingMask:NSViewNotSizable ];
1917         [self addSubview: o_label];
1918
1919         /* build the textfield */
1920         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
1921             28, 49, o_tooltip, @"" )
1922         [o_textfield setFloatValue: p_item->value.f];
1923         [o_textfield setAutoresizingMask:NSViewMaxXMargin ];
1924         [o_textfield setDelegate: self];
1925         [[NSNotificationCenter defaultCenter] addObserver: self
1926             selector: @selector(textfieldChanged:)
1927             name: NSControlTextDidChangeNotification
1928             object: o_textfield];
1929         [self addSubview: o_textfield];
1930
1931         /* build the mintextfield */
1932         ADD_LABEL( o_textfield_min, mainFrame, 12, -30, @"-8888", @"" )
1933         [o_textfield_min setFloatValue: p_item->min.f];
1934         [o_textfield_min setAutoresizingMask:NSViewMaxXMargin ];
1935         [o_textfield_min setAlignment:NSRightTextAlignment];
1936         [self addSubview: o_textfield_min];
1937
1938         /* build the maxtextfield */
1939         ADD_LABEL( o_textfield_max, mainFrame, mainFrame.size.width - 31,
1940             -30, @"8888", @"" )
1941         [o_textfield_max setFloatValue: p_item->max.f];
1942         [o_textfield_max setAutoresizingMask:NSViewMinXMargin ];
1943         [self addSubview: o_textfield_max];
1944
1945         /* build the slider */
1946         ADD_SLIDER( o_slider, mainFrame, [o_textfield_min frame].origin.x +
1947             [o_textfield_min frame].size.width + 6, -1, mainFrame.size.width -
1948             [o_textfield_max frame].size.width -
1949             [o_textfield_max frame].size.width - 14 -
1950             [o_textfield_min frame].origin.x, o_tooltip, p_item->min.f,
1951             p_item->max.f )
1952         [o_slider setFloatValue: p_item->value.f];
1953         [o_slider setAutoresizingMask:NSViewWidthSizable ];
1954         [o_slider setTarget: self];
1955         [o_slider setAction: @selector(sliderChanged:)];
1956         [o_slider sendActionOn:NSLeftMouseUpMask | NSLeftMouseDownMask |
1957             NSLeftMouseDraggedMask];
1958         [self addSubview: o_slider];
1959
1960     }
1961     return self;
1962 }
1963
1964 - (void) alignWithXPosition:(int)i_xPos
1965 {
1966     NSRect frame;
1967     frame = [o_label frame];
1968     frame.origin.x = i_xPos - frame.size.width - 3;
1969     [o_label setFrame:frame];
1970
1971     frame = [o_textfield frame];
1972     frame.origin.x = i_xPos + 2;
1973     [o_textfield setFrame:frame];
1974 }
1975
1976 - (void)dealloc
1977 {
1978     [o_textfield release];
1979     [o_textfield_min release];
1980     [o_textfield_max release];
1981     [o_slider release];
1982     [super dealloc];
1983 }
1984
1985 - (IBAction)sliderChanged:(id)sender
1986 {
1987     [o_textfield setFloatValue: [o_slider floatValue]];
1988 }
1989
1990 - (void)textfieldChanged:(NSNotification *)o_notification
1991 {
1992     [o_slider setFloatValue: [o_textfield floatValue]];
1993 }
1994
1995 - (float)floatValue
1996 {
1997     return [o_slider floatValue];
1998 }
1999
2000 - (void)resetValues
2001 {
2002     [o_textfield setFloatValue: config_GetFloat(VLCIntf, p_item->psz_name)];
2003     [o_slider setFloatValue: config_GetFloat(VLCIntf, p_item->psz_name)];
2004     [super resetValues];
2005 }
2006 @end
2007
2008 @implementation BoolConfigControl
2009
2010 - (id) initWithItem: (module_config_t *)_p_item
2011            withView: (NSView *)o_parent_view
2012 {
2013     NSRect mainFrame = [o_parent_view frame];
2014     NSString *o_labelString, *o_tooltip;
2015     mainFrame.size.height = 17;
2016     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
2017     mainFrame.origin.x = LEFTMARGIN;
2018     mainFrame.origin.y = 0;
2019
2020     if( [super initWithFrame: mainFrame item: _p_item] != nil )
2021     {
2022         i_view_type = CONFIG_ITEM_BOOL;
2023
2024         /* add the checkbox */
2025         o_tooltip = [[VLCMain sharedInstance]
2026             wrapString: [[VLCMain sharedInstance]
2027             localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
2028         ADD_CHECKBOX( o_checkbox, mainFrame, 0,
2029                         0, @"", o_tooltip, p_item->value.i, NSImageLeft)
2030         [o_checkbox setAutoresizingMask:NSViewNotSizable ];
2031         [self addSubview: o_checkbox];
2032         /* add the label */
2033         if( p_item->psz_text )
2034             o_labelString = [[VLCMain sharedInstance]
2035                                 localizedString: (char *)p_item->psz_text];
2036         else
2037             o_labelString = [NSString stringWithString:@""];
2038         ADD_LABEL( o_label, mainFrame, [o_checkbox frame].size.width, 0, o_labelString, o_tooltip )
2039         [o_label setAutoresizingMask:NSViewNotSizable ];
2040         [self addSubview: o_label];
2041     }
2042     return self;
2043 }
2044
2045 - (void)dealloc
2046 {
2047     [o_checkbox release];
2048     [super dealloc];
2049 }
2050
2051 - (int)intValue
2052 {
2053     return [o_checkbox intValue];
2054 }
2055
2056 - (void)resetValues
2057 {
2058     [o_checkbox setState: config_GetInt( VLCIntf, p_item->psz_name)];
2059     [super resetValues];
2060 }
2061 @end
2062
2063 @implementation KeyConfigControl
2064 - (id) initWithItem: (module_config_t *)_p_item
2065            withView: (NSView *)o_parent_view
2066 {
2067     NSRect mainFrame = [o_parent_view frame];
2068     NSString *o_labelString, *o_tooltip;
2069     mainFrame.size.height = 22;
2070     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
2071     mainFrame.origin.x = LEFTMARGIN;
2072     mainFrame.origin.y = 0;
2073
2074     if( [super initWithFrame: mainFrame item: _p_item] != nil )
2075     {
2076         i_view_type = CONFIG_ITEM_KEY;
2077
2078         o_tooltip = [[VLCMain sharedInstance] wrapString:
2079                      [[VLCMain sharedInstance]
2080                       localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
2081
2082         /* add the label */
2083         if( p_item->psz_text )
2084             o_labelString = [[VLCMain sharedInstance]
2085                 localizedString: (char *)p_item->psz_text];
2086         else
2087             o_labelString = [NSString stringWithString:@""];
2088         ADD_LABEL( o_label, mainFrame, 0, -1, o_labelString, o_tooltip )
2089         [o_label setAutoresizingMask:NSViewNotSizable ];
2090         [self addSubview: o_label];
2091
2092         /* build the popup */
2093         ADD_POPUP( o_popup, mainFrame, [o_label frame].origin.x +
2094             [o_label frame].size.width + 3,
2095             -2, 0, o_tooltip )
2096         [o_popup setAutoresizingMask:NSViewWidthSizable ];
2097
2098         if( o_keys_menu == nil )
2099         {
2100             unsigned int i;
2101             o_keys_menu = [[NSMenu alloc] initWithTitle: @"Keys Menu"];
2102 #warning This does not work anymore. FIXME.
2103 #if 0
2104             for ( i = 0; i < sizeof(vlc_key) / sizeof(key_descriptor_t); i++)
2105                 if( vlc_key[i].psz_key_string )
2106                     POPULATE_A_KEY( o_keys_menu,
2107                         [NSString stringWithUTF8String:vlc_key[i].psz_key_string]
2108                         , vlc_key[i].i_key_code)
2109 #endif
2110         }
2111         [o_popup setMenu:[o_keys_menu copyWithZone:nil]];
2112         [o_popup selectItem:[[o_popup menu] itemWithTag:p_item->value.i]];
2113         [self addSubview: o_popup];
2114
2115     }
2116     return self;
2117 }
2118
2119 - (void) alignWithXPosition:(int)i_xPos
2120 {
2121     NSRect frame;
2122     NSRect superFrame = [self frame];
2123     frame = [o_label frame];
2124     frame.origin.x = i_xPos - frame.size.width - 3;
2125     [o_label setFrame:frame];
2126
2127     frame = [o_popup frame];
2128     frame.origin.x = i_xPos - 1;
2129     frame.size.width = superFrame.size.width - frame.origin.x + 2;
2130     [o_popup setFrame:frame];
2131 }
2132
2133 - (void)dealloc
2134 {
2135     [o_popup release];
2136     [super dealloc];
2137 }
2138
2139 - (int)intValue
2140 {
2141     return [o_popup selectedTag];
2142 }
2143
2144 - (void)resetValues
2145 {
2146     [o_popup selectItem:[[o_popup menu] itemWithTag:config_GetInt( VLCIntf, p_item->psz_name )]];
2147     [super resetValues];
2148 }
2149 @end
2150
2151 @implementation ModuleListConfigControl
2152 - (id) initWithItem: (module_config_t *)_p_item
2153            withView: (NSView *)o_parent_view
2154 {
2155     if( _p_item->i_type == CONFIG_ITEM_MODULE_LIST )
2156         //TODO....
2157         return nil;
2158     
2159     //Fill our array to know how may items we have...
2160     module_t *p_parser, **p_list;
2161     size_t i_module_index;
2162     NSRect mainFrame = [o_parent_view frame];
2163     NSString *o_labelString, *o_textfieldString, *o_tooltip;
2164     
2165     o_modulearray = [[NSMutableArray alloc] initWithCapacity:10];
2166     /* build a list of available modules */
2167     p_list = module_list_get( NULL );
2168     for( i_module_index = 0; p_list[i_module_index]; i_module_index++ )
2169     {
2170         int i;
2171         p_parser = p_list[i_module_index];
2172         
2173         if( module_is_main( p_parser ) )
2174             continue;
2175         
2176         unsigned int confsize;
2177         module_config_t *p_configlist = module_config_get( p_parser, &confsize );
2178         
2179         for ( i = 0; i < confsize; i++ )
2180         {
2181             unsigned int unused;
2182             module_config_t *p_config = &p_configlist[i];
2183             NSString *o_modulelongname, *o_modulename;
2184             NSNumber *o_moduleenabled = nil;
2185             
2186             /* Hack: required subcategory is stored in i_min */
2187             if( p_config->i_type == CONFIG_SUBCATEGORY &&
2188                p_config->value.i == _p_item->min.i )
2189             {
2190                 o_modulelongname = [NSString stringWithUTF8String:
2191                                     module_get_name( p_parser, TRUE )];
2192                 o_modulename = [NSString stringWithUTF8String:
2193                                 module_get_object( p_parser )];
2194                 
2195                 if( _p_item->value.psz &&
2196                    strstr( _p_item->value.psz, module_get_object( p_parser ) ) )
2197                     o_moduleenabled = [NSNumber numberWithBool:YES];
2198                 else
2199                     o_moduleenabled = [NSNumber numberWithBool:NO];
2200                 
2201                 [o_modulearray addObject:[NSMutableArray
2202                                           arrayWithObjects: o_modulename, o_modulelongname,
2203                                           o_moduleenabled, nil]];
2204             }
2205         }
2206         module_config_free( p_configlist );
2207     }
2208     module_list_free( p_list );
2209     
2210     mainFrame.size.height = 30 + 20 * [o_modulearray count];
2211     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
2212     mainFrame.origin.x = LEFTMARGIN;
2213     mainFrame.origin.y = 0;
2214     if( [super initWithFrame: mainFrame item: _p_item] != nil )
2215     {
2216         i_view_type = CONFIG_ITEM_MODULE_LIST;
2217         
2218         o_tooltip = [[VLCMain sharedInstance] wrapString:
2219                      [[VLCMain sharedInstance]
2220                       localizedString: (char *)p_item->psz_longtext ] toWidth: PREFS_WRAP];
2221         
2222         /* add the label */
2223         if( p_item->psz_text )
2224             o_labelString = [[VLCMain sharedInstance]
2225                              localizedString: (char *)p_item->psz_text];
2226         else
2227             o_labelString = [NSString stringWithString:@""];
2228         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString, o_tooltip )
2229         [o_label setAutoresizingMask:NSViewNotSizable ];
2230         [self addSubview: o_label];
2231         
2232         /* build the textfield */
2233         if( p_item->value.psz )
2234             o_textfieldString = [[VLCMain sharedInstance]
2235                                  localizedString: (char *)p_item->value.psz];
2236         else
2237             o_textfieldString = [NSString stringWithString: @""];
2238         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
2239                       mainFrame.size.height - 22, mainFrame.size.width -
2240                       [o_label frame].size.width - 2, o_tooltip, o_textfieldString )
2241         [o_textfield setAutoresizingMask:NSViewWidthSizable ];
2242         [self addSubview: o_textfield];
2243         
2244         
2245         {
2246             NSRect s_rc = mainFrame;
2247             s_rc.size.height = mainFrame.size.height - 30;
2248             s_rc.size.width = mainFrame.size.width - 12;
2249             s_rc.origin.x = 12;
2250             s_rc.origin.y = 0;
2251             o_scrollview = [[[NSScrollView alloc] initWithFrame: s_rc] retain];
2252             [o_scrollview setDrawsBackground: NO];
2253             [o_scrollview setBorderType: NSBezelBorder];
2254             [o_scrollview setAutohidesScrollers:YES];
2255             
2256             NSTableView *o_tableview;
2257             o_tableview = [[NSTableView alloc] initWithFrame : s_rc];
2258             [o_tableview setUsesAlternatingRowBackgroundColors:YES];
2259             [o_tableview setHeaderView:nil];
2260             /* TODO: find a good way to fix the row height and text size*/
2261             /* FIXME: support for multiple selection... */
2262             //    [o_tableview setAllowsMultipleSelection:YES];
2263             
2264             NSCell *o_headerCell = [[NSCell alloc] initTextCell:@"Enabled"];
2265             NSCell *o_dataCell = [[NSButtonCell alloc] init];
2266             [(NSButtonCell*)o_dataCell setButtonType:NSSwitchButton];
2267             [o_dataCell setTitle:@""];
2268             [o_dataCell setFont:[NSFont systemFontOfSize:0]];
2269             NSTableColumn *o_tableColumn = [[NSTableColumn alloc]
2270                                             initWithIdentifier:@"Enabled"];
2271             [o_tableColumn setHeaderCell: o_headerCell];
2272             [o_tableColumn setDataCell: o_dataCell];
2273             [o_tableColumn setWidth:17];
2274             [o_tableview addTableColumn: o_tableColumn];
2275             
2276             o_headerCell = [[NSCell alloc] initTextCell:@"Module Name"];
2277             o_dataCell = [[NSTextFieldCell alloc] init];
2278             [o_dataCell setFont:[NSFont systemFontOfSize:12]];
2279             o_tableColumn = [[NSTableColumn alloc]
2280                              initWithIdentifier:@"Module"];
2281             [o_tableColumn setHeaderCell: o_headerCell];
2282             [o_tableColumn setDataCell: o_dataCell];
2283             [o_tableColumn setWidth:s_rc.size.width - 34];
2284             [o_tableview addTableColumn: o_tableColumn];
2285             [o_tableview registerForDraggedTypes:[NSArray arrayWithObjects:
2286                                                   @"VLC media player module", nil]];
2287             
2288             [o_tableview setDataSource:self];
2289             [o_tableview setTarget: self];
2290             [o_tableview setAction: @selector(tableChanged:)];
2291             [o_tableview sendActionOn:NSLeftMouseUpMask | NSLeftMouseDownMask |
2292              NSLeftMouseDraggedMask];
2293             [o_scrollview setDocumentView: o_tableview];
2294         }
2295         [o_scrollview setAutoresizingMask:NSViewWidthSizable ];
2296         [o_scrollview setAutohidesScrollers:YES];
2297         [self addSubview: o_scrollview];
2298
2299     }
2300     return self;
2301 }
2302
2303 - (void) alignWithXPosition:(int)i_xPos
2304 {
2305     ;
2306 }
2307
2308 - (IBAction)tableChanged:(id)sender
2309 {
2310     NSString *o_newstring = @"";
2311     NSUInteger count = [o_modulearray count];
2312     for( NSUInteger i = 0 ; i < count ; i++ )
2313         if( [[[o_modulearray objectAtIndex:i] objectAtIndex:2]
2314             boolValue] != NO )
2315         {
2316             o_newstring = [o_newstring stringByAppendingString:
2317                 [[o_modulearray objectAtIndex:i] objectAtIndex:0]];
2318             o_newstring = [o_newstring stringByAppendingString:@":"];
2319         }
2320
2321     [o_textfield setStringValue: [o_newstring
2322         substringToIndex: ([o_newstring length])?[o_newstring length] - 1:0]];
2323 }
2324
2325 - (void)dealloc
2326 {
2327     [o_scrollview release];
2328     [super dealloc];
2329 }
2330
2331
2332 - (char *)stringValue
2333 {
2334     return strdup( [[o_textfield stringValue] UTF8String] );
2335 }
2336
2337 -(void)resetValues
2338 {
2339 #warning Reset prefs of the module selector is broken atm. 
2340     NSLog( @"don't forget about modulelistconfig" );
2341     [super resetValues];
2342 }
2343
2344 @end
2345
2346 @implementation ModuleListConfigControl (NSTableDataSource)
2347
2348 - (BOOL)tableView:(NSTableView*)table writeRows:(NSArray*)rows
2349     toPasteboard:(NSPasteboard*)pb
2350 {
2351     // We only want to allow dragging of selected rows.
2352     NSEnumerator    *iter = [rows objectEnumerator];
2353     NSNumber        *row;
2354     while ((row = [iter nextObject]) != nil)
2355     {
2356         if (![table isRowSelected:[row intValue]])
2357             return NO;
2358     }
2359
2360     [pb declareTypes:[NSArray
2361         arrayWithObject:@"VLC media player module"] owner:nil];
2362     [pb setPropertyList:rows forType:@"VLC media player module"];
2363     return YES;
2364 }
2365
2366 - (NSDragOperation)tableView:(NSTableView*)table
2367     validateDrop:(id <NSDraggingInfo>)info proposedRow:(NSInteger)row
2368     proposedDropOperation:(NSTableViewDropOperation)op
2369 {
2370     // Make drops at the end of the table go to the end.
2371     if (row == -1)
2372     {
2373         row = [table numberOfRows];
2374         op = NSTableViewDropAbove;
2375         [table setDropRow:row dropOperation:op];
2376     }
2377
2378     // We don't ever want to drop onto a row, only between rows.
2379     if (op == NSTableViewDropOn)
2380         [table setDropRow:(row+1) dropOperation:NSTableViewDropAbove];
2381     return NSTableViewDropAbove;
2382 }
2383
2384 - (BOOL)tableView:(NSTableView*)table acceptDrop:(id <NSDraggingInfo>)info
2385     row:(NSInteger)dropRow dropOperation:(NSTableViewDropOperation)op;
2386 {
2387     NSPasteboard    *pb = [info draggingPasteboard];
2388     NSDragOperation srcMask = [info draggingSourceOperationMask];
2389     BOOL accepted = NO;
2390
2391     NS_DURING
2392
2393         NSArray *array;
2394
2395         // Intra-table drag - data is the array of rows.
2396         if (!accepted && (array =
2397             [pb propertyListForType:@"VLC media player module"]) != NULL)
2398         {
2399             NSEnumerator *iter = nil;
2400             id val;
2401             BOOL isCopy = (srcMask & NSDragOperationMove) ? NO:YES;
2402             // Move the modules
2403             iter = [array objectEnumerator];
2404             while ((val = [iter nextObject]) != NULL)
2405             {
2406                 NSArray *o_tmp = [[o_modulearray objectAtIndex:
2407                     [val intValue]] mutableCopyWithZone:nil];
2408                 [o_modulearray removeObject:o_tmp];
2409                 [o_modulearray insertObject:o_tmp
2410                     atIndex:(dropRow>[val intValue]) ? dropRow - 1 : dropRow];
2411                 dropRow++;
2412             }
2413
2414             // Select the newly-dragged items.
2415             iter = [array objectEnumerator];
2416 //TODO...
2417             [table deselectAll:self];
2418
2419             [self tableChanged:self];
2420             [table setNeedsDisplay:YES];
2421             // Indicate that we finished the drag.
2422             accepted = YES;
2423         }
2424         [table reloadData];
2425         [table setNeedsDisplay:YES];
2426
2427         NS_HANDLER
2428
2429             // An exception occurred. Uh-oh. Update the track table so that
2430             // it stays consistent, and re-raise the exception.
2431             [table reloadData];
2432             [localException raise];
2433             [table setNeedsDisplay:YES];
2434     NS_ENDHANDLER
2435
2436     return accepted;
2437 }
2438
2439 - (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
2440 {
2441     return [o_modulearray count];
2442 }
2443
2444 - (id)tableView:(NSTableView *)aTableView
2445     objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
2446 {
2447     if( [[aTableColumn identifier] isEqualToString: @"Enabled"] )
2448         return [[o_modulearray objectAtIndex:rowIndex] objectAtIndex:2];
2449     if( [[aTableColumn identifier] isEqualToString: @"Module"] )
2450         return [[o_modulearray objectAtIndex:rowIndex] objectAtIndex:1];
2451
2452     return nil;
2453 }
2454
2455 - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject
2456     forTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
2457 {
2458     [[o_modulearray objectAtIndex:rowIndex] replaceObjectAtIndex:2
2459         withObject: anObject];
2460 }
2461 @end