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