]> git.sesse.net Git - vlc/blob - src/config/help.c
Simplify and fix WinCE build
[vlc] / src / config / help.c
1 /*****************************************************************************
2  * help.c: command line help
3  *****************************************************************************
4  * Copyright (C) 1998-2011 the VideoLAN team
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <vlc_common.h>
26 #include <vlc_charset.h>
27 #include <vlc_modules.h>
28 #include "modules/modules.h"
29 #include "config/configuration.h"
30 #include "libvlc.h"
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #elif defined( WIN32 ) && !defined( UNDER_CE )
38 # include <io.h>
39 #endif
40 #if defined( WIN32 ) && !defined( UNDER_CE )
41 static void ShowConsole (void);
42 static void PauseConsole (void);
43 #else
44 # define ShowConsole() (void)0
45 # define PauseConsole() (void)0
46 #endif
47
48 static void Help (vlc_object_t *, const char *);
49 static void Usage (vlc_object_t *, const char *);
50 static void Version (void);
51 static void ListModules (vlc_object_t *, bool);
52 static int ConsoleWidth (void);
53
54 /**
55  * Checks for help command line options such as --help or --version.
56  * If one is found, print the corresponding text.
57  * \return true if a command line options caused some help message to be
58  * printed, false otherwise. 
59  */
60 bool config_PrintHelp (vlc_object_t *obj)
61 {
62     char *str;
63
64     /* Check for short help option */
65     if (var_InheritBool (obj, "help"))
66     {
67         Help (obj, "help");
68         return true;
69     }
70
71     /* Check for version option */
72     if (var_InheritBool (obj, "version"))
73     {
74         Version();
75         return true;
76     }
77
78     /* Check for help on modules */
79     str = var_InheritString (obj, "module");
80     if (str != NULL)
81     {
82         Help (obj, str);
83         free (str);
84         return true;
85     }
86
87     /* Check for full help option */
88     if (var_InheritBool (obj, "full-help"))
89     {
90         var_Create (obj, "advanced", VLC_VAR_BOOL);
91         var_SetBool (obj, "advanced", true);
92         var_Create (obj, "help-verbose", VLC_VAR_BOOL);
93         var_SetBool (obj, "help-verbose", true);
94         Help (obj, "full-help");
95         return true;
96     }
97
98     /* Check for long help option */
99     if (var_InheritBool (obj, "longhelp"))
100     {
101         Help (obj, "longhelp");
102         return true;
103     }
104
105     /* Check for module list option */
106     if (var_InheritBool (obj, "list"))
107     {
108         ListModules (obj, false );
109         return true;
110     }
111
112     if (var_InheritBool (obj, "list-verbose"))
113     {
114         ListModules (obj, true);
115         return true;
116     }
117
118     return false;
119 }
120
121 /*****************************************************************************
122  * Help: print program help
123  *****************************************************************************
124  * Print a short inline help. Message interface is initialized at this stage.
125  *****************************************************************************/
126 static inline void print_help_on_full_help( void )
127 {
128     utf8_fprintf( stdout, "\n" );
129     utf8_fprintf( stdout, "%s\n", _("To get exhaustive help, use '-H'.") );
130 }
131
132 static const char vlc_usage[] = N_(
133   "Usage: %s [options] [stream] ...\n"
134   "You can specify multiple streams on the commandline.\n"
135   "They will be enqueued in the playlist.\n"
136   "The first item specified will be played first.\n"
137   "\n"
138   "Options-styles:\n"
139   "  --option  A global option that is set for the duration of the program.\n"
140   "   -option  A single letter version of a global --option.\n"
141   "   :option  An option that only applies to the stream directly before it\n"
142   "            and that overrides previous settings.\n"
143   "\n"
144   "Stream MRL syntax:\n"
145   "  [[access][/demux]://]URL[@[title][:chapter][-[title][:chapter]]]\n"
146   "  [:option=value ...]\n"
147   "\n"
148   "  Many of the global --options can also be used as MRL specific :options.\n"
149   "  Multiple :option=value pairs can be specified.\n"
150   "\n"
151   "URL syntax:\n"
152   "  file:///path/file              Plain media file\n"
153   "  http://host[:port]/file        HTTP URL\n"
154   "  ftp://host[:port]/file         FTP URL\n"
155   "  mms://host[:port]/file         MMS URL\n"
156   "  screen://                      Screen capture\n"
157   "  dvd://[device][@raw_device]    DVD device\n"
158   "  vcd://[device]                 VCD device\n"
159   "  cdda://[device]                Audio CD device\n"
160   "  udp://[[<source address>]@[<bind address>][:<bind port>]]\n"
161   "                                 UDP stream sent by a streaming server\n"
162   "  vlc://pause:<seconds>          Pause the playlist for a certain time\n"
163   "  vlc://quit                     Special item to quit VLC\n"
164   "\n");
165
166 static void Help (vlc_object_t *p_this, char const *psz_help_name)
167 {
168     ShowConsole();
169
170     if( psz_help_name && !strcmp( psz_help_name, "help" ) )
171     {
172         utf8_fprintf( stdout, vlc_usage, "vlc" );
173         Usage( p_this, "=help" );
174         Usage( p_this, "=main" );
175         print_help_on_full_help();
176     }
177     else if( psz_help_name && !strcmp( psz_help_name, "longhelp" ) )
178     {
179         utf8_fprintf( stdout, vlc_usage, "vlc" );
180         Usage( p_this, NULL );
181         print_help_on_full_help();
182     }
183     else if( psz_help_name && !strcmp( psz_help_name, "full-help" ) )
184     {
185         utf8_fprintf( stdout, vlc_usage, "vlc" );
186         Usage( p_this, NULL );
187     }
188     else if( psz_help_name )
189     {
190         Usage( p_this, psz_help_name );
191     }
192
193     PauseConsole();
194 }
195
196 /*****************************************************************************
197  * Usage: print module usage
198  *****************************************************************************
199  * Print a short inline help. Message interface is initialized at this stage.
200  *****************************************************************************/
201 #   define COL(x)  "\033[" #x ";1m"
202 #   define RED     COL(31)
203 #   define GREEN   COL(32)
204 #   define YELLOW  COL(33)
205 #   define BLUE    COL(34)
206 #   define MAGENTA COL(35)
207 #   define CYAN    COL(36)
208 #   define WHITE   COL(0)
209 #   define GRAY    "\033[0m"
210 static void
211 print_help_section( const module_t *m, const module_config_t *p_item,
212                     bool b_color, bool b_description )
213 {
214     if( !p_item ) return;
215     if( b_color )
216     {
217         utf8_fprintf( stdout, RED"   %s:\n"GRAY,
218                       module_gettext( m, p_item->psz_text ) );
219         if( b_description && p_item->psz_longtext )
220             utf8_fprintf( stdout, MAGENTA"   %s\n"GRAY,
221                           module_gettext( m, p_item->psz_longtext ) );
222     }
223     else
224     {
225         utf8_fprintf( stdout, "   %s:\n",
226                       module_gettext( m, p_item->psz_text ) );
227         if( b_description && p_item->psz_longtext )
228             utf8_fprintf( stdout, "   %s\n",
229                           module_gettext(m, p_item->psz_longtext ) );
230     }
231 }
232
233 static void Usage (vlc_object_t *p_this, char const *psz_search)
234 {
235 #define FORMAT_STRING "  %s --%s%s%s%s%s%s%s "
236     /* short option ------'    | | | | | | |
237      * option name ------------' | | | | | |
238      * <bra ---------------------' | | | | |
239      * option type or "" ----------' | | | |
240      * ket> -------------------------' | | |
241      * padding spaces -----------------' | |
242      * comment --------------------------' |
243      * comment suffix ---------------------'
244      *
245      * The purpose of having bra and ket is that we might i18n them as well.
246      */
247
248 #define COLOR_FORMAT_STRING (WHITE"  %s --%s"YELLOW"%s%s%s%s%s%s "GRAY)
249 #define COLOR_FORMAT_STRING_BOOL (WHITE"  %s --%s%s%s%s%s%s%s "GRAY)
250
251 #define LINE_START 8
252 #define PADDING_SPACES 25
253 #ifdef WIN32
254 #   define OPTION_VALUE_SEP "="
255 #else
256 #   define OPTION_VALUE_SEP " "
257 #endif
258     char psz_spaces_text[PADDING_SPACES+LINE_START+1];
259     char psz_spaces_longtext[LINE_START+3];
260     char psz_format[sizeof(COLOR_FORMAT_STRING)];
261     char psz_format_bool[sizeof(COLOR_FORMAT_STRING_BOOL)];
262     char psz_buffer[10000];
263     char psz_short[4];
264     int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
265     int i_width_description = i_width + PADDING_SPACES - 1;
266     bool b_advanced    = var_InheritBool( p_this, "advanced" );
267     bool b_description = var_InheritBool( p_this, "help-verbose" );
268     bool b_description_hack;
269     bool b_color       = var_InheritBool( p_this, "color" );
270     bool b_has_advanced = false;
271     bool b_found       = false;
272     int  i_only_advanced = 0; /* Number of modules ignored because they
273                                * only have advanced options */
274     bool b_strict = psz_search && *psz_search == '=';
275     if( b_strict ) psz_search++;
276
277     memset( psz_spaces_text, ' ', PADDING_SPACES+LINE_START );
278     psz_spaces_text[PADDING_SPACES+LINE_START] = '\0';
279     memset( psz_spaces_longtext, ' ', LINE_START+2 );
280     psz_spaces_longtext[LINE_START+2] = '\0';
281 #ifndef WIN32
282     if( !isatty( 1 ) )
283 #endif
284         b_color = false; // don't put color control codes in a .txt file
285
286     if( b_color )
287     {
288         strcpy( psz_format, COLOR_FORMAT_STRING );
289         strcpy( psz_format_bool, COLOR_FORMAT_STRING_BOOL );
290     }
291     else
292     {
293         strcpy( psz_format, FORMAT_STRING );
294         strcpy( psz_format_bool, FORMAT_STRING );
295     }
296
297     /* List all modules */
298     module_t **list = module_list_get (NULL);
299     if (!list)
300         return;
301
302     /* Ugly hack to make sure that the help options always come first
303      * (part 1) */
304     if( !psz_search )
305         Usage( p_this, "help" );
306
307     /* Enumerate the config for each module */
308     for (size_t i = 0; list[i]; i++)
309     {
310         bool b_help_module;
311         module_t *p_parser = list[i];
312         module_config_t *p_item = NULL;
313         module_config_t *p_section = NULL;
314         module_config_t *p_end = p_parser->p_config + p_parser->confsize;
315         const char *objname = module_get_object (p_parser);
316
317         if( psz_search &&
318             ( b_strict ? strcmp( objname, psz_search )
319                        : !strstr( objname, psz_search ) ) )
320         {
321             char *const *pp_shortcuts = p_parser->pp_shortcuts;
322             unsigned i;
323             for( i = 0; i < p_parser->i_shortcuts; i++ )
324             {
325                 if( b_strict ? !strcmp( psz_search, pp_shortcuts[i] )
326                              : !!strstr( pp_shortcuts[i], psz_search ) )
327                     break;
328             }
329             if( i == p_parser->i_shortcuts )
330                 continue;
331         }
332
333         /* Ignore modules without config options */
334         if( !p_parser->i_config_items )
335         {
336             continue;
337         }
338
339         b_help_module = !strcmp( "help", objname );
340         /* Ugly hack to make sure that the help options always come first
341          * (part 2) */
342         if( !psz_search && b_help_module )
343             continue;
344
345         /* Ignore modules with only advanced config options if requested */
346         if( !b_advanced )
347         {
348             for( p_item = p_parser->p_config;
349                  p_item < p_end;
350                  p_item++ )
351             {
352                 if( CONFIG_ITEM(p_item->i_type) &&
353                     !p_item->b_advanced && !p_item->b_removed ) break;
354             }
355
356             if( p_item == p_end )
357             {
358                 i_only_advanced++;
359                 continue;
360             }
361         }
362
363         b_found = true;
364
365         /* Print name of module */
366         if( strcmp( "main", objname ) )
367         {
368             if( b_color )
369                 utf8_fprintf( stdout, "\n " GREEN "%s" GRAY " (%s)\n",
370                               module_gettext( p_parser, p_parser->psz_longname ),
371                               objname );
372             else
373                 utf8_fprintf( stdout, "\n %s\n",
374                               module_gettext(p_parser, p_parser->psz_longname ) );
375         }
376         if( p_parser->psz_help )
377         {
378             if( b_color )
379                 utf8_fprintf( stdout, CYAN" %s\n"GRAY,
380                               module_gettext( p_parser, p_parser->psz_help ) );
381             else
382                 utf8_fprintf( stdout, " %s\n",
383                               module_gettext( p_parser, p_parser->psz_help ) );
384         }
385
386         /* Print module options */
387         for( p_item = p_parser->p_config;
388              p_item < p_end;
389              p_item++ )
390         {
391             char *psz_text, *psz_spaces = psz_spaces_text;
392             const char *psz_bra = NULL, *psz_type = NULL, *psz_ket = NULL;
393             const char *psz_suf = "", *psz_prefix = NULL;
394             signed int i;
395             size_t i_cur_width;
396
397             /* Skip removed options */
398             if( p_item->b_removed )
399             {
400                 continue;
401             }
402             /* Skip advanced options if requested */
403             if( p_item->b_advanced && !b_advanced )
404             {
405                 b_has_advanced = true;
406                 continue;
407             }
408
409             switch( CONFIG_CLASS(p_item->i_type) )
410             {
411             case 0: // hint class
412                 switch( p_item->i_type )
413                 {
414                 case CONFIG_HINT_CATEGORY:
415                 case CONFIG_HINT_USAGE:
416                     if( !strcmp( "main", objname ) )
417                     {
418                         if( b_color )
419                             utf8_fprintf( stdout, GREEN "\n %s\n" GRAY,
420                                           module_gettext( p_parser, p_item->psz_text ) );
421                         else
422                             utf8_fprintf( stdout, "\n %s\n",
423                                           module_gettext( p_parser, p_item->psz_text ) );
424                     }
425                     if( b_description && p_item->psz_longtext )
426                     {
427                         if( b_color )
428                             utf8_fprintf( stdout, CYAN " %s\n" GRAY,
429                                           module_gettext( p_parser, p_item->psz_longtext ) );
430                         else
431                             utf8_fprintf( stdout, " %s\n",
432                                           module_gettext( p_parser, p_item->psz_longtext ) );
433                 }
434                 break;
435
436                 case CONFIG_HINT_SUBCATEGORY:
437                     if( strcmp( "main", objname ) )
438                         break;
439                 case CONFIG_SECTION:
440                     p_section = p_item;
441                     break;
442                 }
443                 break;
444
445             case CONFIG_ITEM_STRING:
446                 print_help_section( p_parser, p_section, b_color,
447                                     b_description );
448                 p_section = NULL;
449                 psz_bra = OPTION_VALUE_SEP "<";
450                 psz_type = _("string");
451                 psz_ket = ">";
452
453                 if( p_item->ppsz_list )
454                 {
455                     psz_bra = OPTION_VALUE_SEP "{";
456                     psz_type = psz_buffer;
457                     psz_buffer[0] = '\0';
458                     for( i = 0; p_item->ppsz_list[i]; i++ )
459                     {
460                         if( i ) strcat( psz_buffer, "," );
461                         strcat( psz_buffer, p_item->ppsz_list[i] );
462                     }
463                     psz_ket = "}";
464                 }
465                 break;
466             case CONFIG_ITEM_INTEGER:
467                 print_help_section( p_parser, p_section, b_color,
468                                     b_description );
469                 p_section = NULL;
470                 psz_bra = OPTION_VALUE_SEP "<";
471                 psz_type = _("integer");
472                 psz_ket = ">";
473
474                 if( p_item->min.i || p_item->max.i )
475                 {
476                     sprintf( psz_buffer, "%s [%"PRId64" .. %"PRId64"]",
477                              psz_type, p_item->min.i, p_item->max.i );
478                     psz_type = psz_buffer;
479                 }
480
481                 if( p_item->i_list )
482                 {
483                     psz_bra = OPTION_VALUE_SEP "{";
484                     psz_type = psz_buffer;
485                     psz_buffer[0] = '\0';
486                     for( i = 0; p_item->ppsz_list_text[i]; i++ )
487                     {
488                         if( i ) strcat( psz_buffer, ", " );
489                         sprintf( psz_buffer + strlen(psz_buffer), "%i (%s)",
490                                  p_item->pi_list[i],
491                                  module_gettext( p_parser, p_item->ppsz_list_text[i] ) );
492                     }
493                     psz_ket = "}";
494                 }
495                 break;
496             case CONFIG_ITEM_FLOAT:
497                 print_help_section( p_parser, p_section, b_color,
498                                     b_description );
499                 p_section = NULL;
500                 psz_bra = OPTION_VALUE_SEP "<";
501                 psz_type = _("float");
502                 psz_ket = ">";
503                 if( p_item->min.f || p_item->max.f )
504                 {
505                     sprintf( psz_buffer, "%s [%f .. %f]", psz_type,
506                              p_item->min.f, p_item->max.f );
507                     psz_type = psz_buffer;
508                 }
509                 break;
510             case CONFIG_ITEM_BOOL:
511                 print_help_section( p_parser, p_section, b_color,
512                                     b_description );
513                 p_section = NULL;
514                 psz_bra = ""; psz_type = ""; psz_ket = "";
515                 if( !b_help_module )
516                 {
517                     psz_suf = p_item->value.i ? _(" (default enabled)") :
518                                                 _(" (default disabled)");
519                 }
520                 break;
521             }
522
523             if( !psz_type )
524             {
525                 continue;
526             }
527
528             /* Add short option if any */
529             if( p_item->i_short )
530             {
531                 sprintf( psz_short, "-%c,", p_item->i_short );
532             }
533             else
534             {
535                 strcpy( psz_short, "   " );
536             }
537
538             i = PADDING_SPACES - strlen( p_item->psz_name )
539                  - strlen( psz_bra ) - strlen( psz_type )
540                  - strlen( psz_ket ) - 1;
541
542             if( CONFIG_CLASS(p_item->i_type) == CONFIG_ITEM_BOOL
543              && !b_help_module )
544             {
545                 psz_prefix =  ", --no-";
546                 i -= strlen( p_item->psz_name ) + strlen( psz_prefix );
547             }
548
549             if( i < 0 )
550             {
551                 psz_spaces[0] = '\n';
552                 i = 0;
553             }
554             else
555             {
556                 psz_spaces[i] = '\0';
557             }
558
559             if( CONFIG_CLASS(p_item->i_type) == CONFIG_ITEM_BOOL
560              && !b_help_module )
561             {
562                 utf8_fprintf( stdout, psz_format_bool, psz_short,
563                               p_item->psz_name, psz_prefix, p_item->psz_name,
564                               psz_bra, psz_type, psz_ket, psz_spaces );
565             }
566             else
567             {
568                 utf8_fprintf( stdout, psz_format, psz_short, p_item->psz_name,
569                          "", "", psz_bra, psz_type, psz_ket, psz_spaces );
570             }
571
572             psz_spaces[i] = ' ';
573
574             /* We wrap the rest of the output */
575             sprintf( psz_buffer, "%s%s", module_gettext( p_parser, p_item->psz_text ),
576                      psz_suf );
577             b_description_hack = b_description;
578
579  description:
580             psz_text = psz_buffer;
581             i_cur_width = b_description && !b_description_hack
582                           ? i_width_description
583                           : i_width;
584             if( !*psz_text ) strcpy(psz_text, " ");
585             while( *psz_text )
586             {
587                 char *psz_parser, *psz_word;
588                 size_t i_end = strlen( psz_text );
589
590                 /* If the remaining text fits in a line, print it. */
591                 if( i_end <= i_cur_width )
592                 {
593                     if( b_color )
594                     {
595                         if( !b_description || b_description_hack )
596                             utf8_fprintf( stdout, BLUE"%s\n"GRAY, psz_text );
597                         else
598                             utf8_fprintf( stdout, "%s\n", psz_text );
599                     }
600                     else
601                     {
602                         utf8_fprintf( stdout, "%s\n", psz_text );
603                     }
604                     break;
605                 }
606
607                 /* Otherwise, eat as many words as possible */
608                 psz_parser = psz_text;
609                 do
610                 {
611                     psz_word = psz_parser;
612                     psz_parser = strchr( psz_word, ' ' );
613                     /* If no space was found, we reached the end of the text
614                      * block; otherwise, we skip the space we just found. */
615                     psz_parser = psz_parser ? psz_parser + 1
616                                             : psz_text + i_end;
617
618                 } while( (size_t)(psz_parser - psz_text) <= i_cur_width );
619
620                 /* We cut a word in one of these cases:
621                  *  - it's the only word in the line and it's too long.
622                  *  - we used less than 80% of the width and the word we are
623                  *    going to wrap is longer than 40% of the width, and even
624                  *    if the word would have fit in the next line. */
625                 if( psz_word == psz_text
626              || ( (size_t)(psz_word - psz_text) < 80 * i_cur_width / 100
627              && (size_t)(psz_parser - psz_word) > 40 * i_cur_width / 100 ) )
628                 {
629                     char c = psz_text[i_cur_width];
630                     psz_text[i_cur_width] = '\0';
631                     if( b_color )
632                     {
633                         if( !b_description || b_description_hack )
634                             utf8_fprintf( stdout, BLUE"%s\n%s"GRAY,
635                                           psz_text, psz_spaces );
636                         else
637                             utf8_fprintf( stdout, "%s\n%s",
638                                           psz_text, psz_spaces );
639                     }
640                     else
641                     {
642                         utf8_fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
643                     }
644                     psz_text += i_cur_width;
645                     psz_text[0] = c;
646                 }
647                 else
648                 {
649                     psz_word[-1] = '\0';
650                     if( b_color )
651                     {
652                         if( !b_description || b_description_hack )
653                             utf8_fprintf( stdout, BLUE"%s\n%s"GRAY,
654                                           psz_text, psz_spaces );
655                         else
656                             utf8_fprintf( stdout, "%s\n%s",
657                                           psz_text, psz_spaces );
658                     }
659                     else
660                     {
661                         utf8_fprintf( stdout, "%s\n%s", psz_text, psz_spaces );
662                     }
663                     psz_text = psz_word;
664                 }
665             }
666
667             if( b_description_hack && p_item->psz_longtext )
668             {
669                 sprintf( psz_buffer, "%s%s",
670                          module_gettext( p_parser, p_item->psz_longtext ),
671                          psz_suf );
672                 b_description_hack = false;
673                 psz_spaces = psz_spaces_longtext;
674                 utf8_fprintf( stdout, "%s", psz_spaces );
675                 goto description;
676             }
677         }
678     }
679
680     if( b_has_advanced )
681     {
682         if( b_color )
683             utf8_fprintf( stdout, "\n" WHITE "%s" GRAY " %s\n", _( "Note:" ),
684            _( "add --advanced to your command line to see advanced options."));
685         else
686             utf8_fprintf( stdout, "\n%s %s\n", _( "Note:" ),
687            _( "add --advanced to your command line to see advanced options."));
688     }
689
690     if( i_only_advanced > 0 )
691     {
692         if( b_color )
693         {
694             utf8_fprintf( stdout, "\n" WHITE "%s" GRAY " ", _( "Note:" ) );
695             utf8_fprintf( stdout, _( "%d module(s) were not displayed because they only have advanced options.\n" ), i_only_advanced );
696         }
697         else
698         {
699             utf8_fprintf( stdout, "\n%s ", _( "Note:" ) );
700             utf8_fprintf( stdout, _( "%d module(s) were not displayed because they only have advanced options.\n" ), i_only_advanced );
701         }
702     }
703     else if( !b_found )
704     {
705         if( b_color )
706             utf8_fprintf( stdout, "\n" WHITE "%s" GRAY "\n",
707                        _( "No matching module found. Use --list or " \
708                           "--list-verbose to list available modules." ) );
709         else
710             utf8_fprintf( stdout, "\n%s\n",
711                        _( "No matching module found. Use --list or " \
712                           "--list-verbose to list available modules." ) );
713     }
714
715     /* Release the module list */
716     module_list_free (list);
717 }
718
719 /*****************************************************************************
720  * ListModules: list the available modules with their description
721  *****************************************************************************
722  * Print a list of all available modules (builtins and plugins) and a short
723  * description for each one.
724  *****************************************************************************/
725 static void ListModules (vlc_object_t *p_this, bool b_verbose)
726 {
727     module_t *p_parser;
728
729     bool b_color = var_InheritBool( p_this, "color" );
730
731     ShowConsole();
732 #ifdef WIN32
733     b_color = false; // don't put color control codes in a .txt file
734 #else
735     if( !isatty( 1 ) )
736         b_color = false;
737 #endif
738
739     /* List all modules */
740     module_t **list = module_list_get (NULL);
741
742     /* Enumerate each module */
743     for (size_t j = 0; (p_parser = list[j]) != NULL; j++)
744     {
745         const char *objname = module_get_object (p_parser);
746         if( b_color )
747             utf8_fprintf( stdout, GREEN"  %-22s "WHITE"%s\n"GRAY, objname,
748                           module_gettext( p_parser, p_parser->psz_longname ) );
749         else
750             utf8_fprintf( stdout, "  %-22s %s\n", objname,
751                           module_gettext( p_parser, p_parser->psz_longname ) );
752
753         if( b_verbose )
754         {
755             char *const *pp_shortcuts = p_parser->pp_shortcuts;
756             for( unsigned i = 0; i < p_parser->i_shortcuts; i++ )
757             {
758                 if( strcmp( pp_shortcuts[i], objname ) )
759                 {
760                     if( b_color )
761                         utf8_fprintf( stdout, CYAN"   s %s\n"GRAY,
762                                       pp_shortcuts[i] );
763                     else
764                         utf8_fprintf( stdout, "   s %s\n",
765                                       pp_shortcuts[i] );
766                 }
767             }
768             if( p_parser->psz_capability )
769             {
770                 if( b_color )
771                     utf8_fprintf( stdout, MAGENTA"   c %s (%d)\n"GRAY,
772                                   p_parser->psz_capability,
773                                   p_parser->i_score );
774                 else
775                     utf8_fprintf( stdout, "   c %s (%d)\n",
776                                   p_parser->psz_capability,
777                                   p_parser->i_score );
778             }
779         }
780     }
781     module_list_free (list);
782     PauseConsole();
783 }
784
785 /*****************************************************************************
786  * Version: print complete program version
787  *****************************************************************************
788  * Print complete program version and build number.
789  *****************************************************************************/
790 static void Version( void )
791 {
792     ShowConsole();
793     utf8_fprintf( stdout, _("VLC version %s (%s)\n"), VERSION_MESSAGE,
794                   psz_vlc_changeset );
795     utf8_fprintf( stdout, _("Compiled by %s on %s (%s)\n"),
796              VLC_CompileBy(), VLC_CompileHost(), __DATE__" "__TIME__ );
797     utf8_fprintf( stdout, _("Compiler: %s\n"), VLC_Compiler() );
798     utf8_fprintf( stdout, "%s", LICENSE_MSG );
799     PauseConsole();
800 }
801
802 #if defined (WIN32) && !defined (UNDER_CE)
803 /*****************************************************************************
804  * ShowConsole: On Win32, create an output console for debug messages
805  *****************************************************************************
806  * This function is useful only on Win32.
807  *****************************************************************************/
808 static void ShowConsole( void )
809 {
810     FILE *f_help = NULL;
811
812     if( getenv( "PWD" ) ) return; /* Cygwin shell or Wine */
813
814     AllocConsole();
815     /* Use the ANSI code page (e.g. Windows-1252) as expected by the LibVLC
816      * Unicode/locale subsystem. By default, we have the obsolecent OEM code
817      * page (e.g. CP437 or CP850). */
818     SetConsoleOutputCP (GetACP ());
819     SetConsoleTitle ("VLC media player version "PACKAGE_VERSION);
820
821     freopen( "CONOUT$", "w", stderr );
822     freopen( "CONIN$", "r", stdin );
823
824     f_help = fopen( "vlc-help.txt", "wt" );
825     if( f_help != NULL )
826     {
827         fclose( f_help );
828         freopen( "vlc-help.txt", "wt", stdout );
829         utf8_fprintf( stderr, _("\nDumped content to vlc-help.txt file.\n") );
830     }
831     else freopen( "CONOUT$", "w", stdout );
832 }
833
834 /*****************************************************************************
835  * PauseConsole: On Win32, wait for a key press before closing the console
836  *****************************************************************************
837  * This function is useful only on Win32.
838  *****************************************************************************/
839 static void PauseConsole( void )
840 {
841     if( getenv( "PWD" ) ) return; /* Cygwin shell or Wine */
842
843     utf8_fprintf( stderr, _("\nPress the RETURN key to continue...\n") );
844     getchar();
845     fclose( stdout );
846 }
847 #endif
848
849 /*****************************************************************************
850  * ConsoleWidth: Return the console width in characters
851  *****************************************************************************
852  * We use the stty shell command to get the console width; if this fails or
853  * if the width is less than 80, we default to 80.
854  *****************************************************************************/
855 static int ConsoleWidth( void )
856 {
857     unsigned i_width = 80;
858
859 #ifndef WIN32
860     FILE *file = popen( "stty size 2>/dev/null", "r" );
861     if (file != NULL)
862     {
863         if (fscanf (file, "%*u %u", &i_width) <= 0)
864             i_width = 80;
865         pclose( file );
866     }
867 #elif !defined (UNDER_CE)
868     CONSOLE_SCREEN_BUFFER_INFO buf;
869
870     if (GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &buf))
871         i_width = buf.dwSize.X;
872 #endif
873
874     return i_width;
875 }