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