1 /*****************************************************************
2 * gmerlin - a general purpose multimedia framework and applications
3 *
4 * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5 * gmerlin-general@lists.sourceforge.net
6 * http://gmerlin.sourceforge.net
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * *****************************************************************/
21
22
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <time.h>
29
30 #include <config.h>
31 #include <gmerlin/translation.h>
32
33 #include <gmerlin/cfg_registry.h>
34 #include <gmerlin/cmdline.h>
35 #include <gmerlin/utils.h>
36
37 static const bg_cmdline_app_data_t * app_data;
38
39
40 /* Terminal related functions */
41
42 #define MAX_COLS 79 /* For line-wrapping */
43
44 static void opt_help(void * data, int * argc, char *** argv, int arg);
45 static void opt_help_man(void * data, int * argc, char *** argv, int arg);
46 static void opt_help_texi(void * data, int * argc, char *** argv, int arg);
47 static void opt_version(void * data, int * argc, char *** argv, int arg);
48
do_indent(FILE * out,int num,bg_help_format_t format)49 static void do_indent(FILE * out, int num, bg_help_format_t format)
50 {
51 switch(format)
52 {
53 case BG_HELP_FORMAT_TERM:
54 case BG_HELP_FORMAT_PLAIN:
55 {
56 int i;
57 for(i = 0; i < num; i++)
58 fprintf(out, " ");
59 }
60 break;
61 case BG_HELP_FORMAT_MAN:
62 // fprintf(out, ".RS %d\n", num);
63 break;
64 case BG_HELP_FORMAT_TEXI:
65 break;
66 }
67 }
68
dump_string_term(FILE * out,const char * str,int indent,const char * translation_domain,bg_help_format_t format)69 static void dump_string_term(FILE * out, const char * str, int indent,
70 const char * translation_domain, bg_help_format_t format)
71 {
72 const char * start;
73 const char * end;
74 const char * pos;
75
76 str = TR_DOM(str);
77
78 if(format == BG_HELP_FORMAT_MAN)
79 do_indent(out, indent + 2, format);
80
81 start = str;
82 pos = str;
83 end = str;
84
85 while(1)
86 {
87 if(isspace(*pos))
88 end = pos;
89
90 if(pos - start + indent + 2 > MAX_COLS)
91 {
92 if(format != BG_HELP_FORMAT_MAN)
93 do_indent(out, indent + 2, format);
94
95 fwrite(start, 1, end - start, out);
96
97 fprintf(out, "\n");
98
99 while(isspace(*end))
100 end++;
101 start = end;
102 }
103 else if(*pos == '\0')
104 {
105 if(format != BG_HELP_FORMAT_MAN)
106 do_indent(out, indent + 2, format);
107
108 fwrite(start, 1, pos - start, out);
109 fprintf(out, "\n");
110 break;
111 }
112 else if(*pos == '\n')
113 {
114 if(format != BG_HELP_FORMAT_MAN)
115 do_indent(out, indent + 2, format);
116
117 fwrite(start, 1, pos - start, out);
118
119 if(format == BG_HELP_FORMAT_TEXI)
120 fprintf(out, "@*\n");
121 else
122 fprintf(out, "\n");
123
124 pos++;
125
126 start = pos;
127 end = pos;
128 }
129
130 else
131 pos++;
132 }
133
134 }
135
136 static const char ansi_underline[] = { 27, '[', '4', 'm', '\0' };
137 static const char ansi_normal[] = { 27, '[', '0', 'm', '\0' };
138 static const char ansi_bold[] = { 27, '[', '1', 'm', '\0' };
139
print_string(FILE * out,const char * str,bg_help_format_t format)140 static void print_string(FILE * out, const char * str, bg_help_format_t format)
141 {
142 switch(format)
143 {
144 case BG_HELP_FORMAT_TEXI:
145 {
146 const char * pos;
147 pos = str;
148 while(*pos)
149 {
150 if((*pos == '{') || (*pos == '}') || (*pos == '@'))
151 fprintf(out, "@%c", *pos);
152 else
153 fprintf(out, "%c", *pos);
154 pos++;
155 }
156 }
157 break;
158 default:
159 fprintf(out, "%s", str);
160 break;
161 }
162 }
163
print_bold(FILE * out,char * str,bg_help_format_t format)164 static void print_bold(FILE * out, char * str, bg_help_format_t format)
165 {
166 switch(format)
167 {
168 case BG_HELP_FORMAT_TERM:
169 fprintf(out, "%s%s%s", ansi_bold, str, ansi_normal);
170 break;
171 case BG_HELP_FORMAT_PLAIN:
172 fprintf(out, "%s", str);
173 /* Do nothing */
174 break;
175 case BG_HELP_FORMAT_MAN:
176 fprintf(out, ".B %s\n", str);
177 break;
178 case BG_HELP_FORMAT_TEXI:
179 fprintf(out, "@b{");
180 print_string(out, str, format);
181 fprintf(out, "}");
182 break;
183 }
184 }
185
print_italic(FILE * out,char * str,bg_help_format_t format)186 static void print_italic(FILE * out, char * str, bg_help_format_t format)
187 {
188 switch(format)
189 {
190 case BG_HELP_FORMAT_TERM:
191 fprintf(out, "%s%s%s", ansi_underline, str, ansi_normal);
192 break;
193 case BG_HELP_FORMAT_PLAIN:
194 /* Do nothing */
195 fprintf(out, "%s", str);
196 break;
197 case BG_HELP_FORMAT_MAN:
198 fprintf(out, ".I %s\n", str);
199 break;
200 case BG_HELP_FORMAT_TEXI:
201 fprintf(out, "@i{");
202 print_string(out, str, format);
203 fprintf(out, "}");
204 break;
205 }
206 }
207
print_linebreak(FILE * out,bg_help_format_t format)208 static void print_linebreak(FILE * out, bg_help_format_t format)
209 {
210 if(format == BG_HELP_FORMAT_MAN)
211 fprintf(out, "\n.P\n");
212 else if(format == BG_HELP_FORMAT_TEXI)
213 fprintf(out, "@*@*\n");
214 else
215 fprintf(out, "\n\n");
216 }
217
print_version(const bg_cmdline_app_data_t * app_data)218 static void print_version(const bg_cmdline_app_data_t * app_data)
219 {
220 printf("%s (%s) %s\n", app_data->name, app_data->package, app_data->version);
221 printf(TR("Copyright (C) 2001-2007 Members of the gmerlin project\n"));
222 printf(TR("This is free software. You may redistribute copies of it under the terms of\n\
223 the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.\n\
224 There is NO WARRANTY.\n"));
225 }
226
print_help(const bg_cmdline_arg_t * args,bg_help_format_t format)227 static void print_help(const bg_cmdline_arg_t* args, bg_help_format_t format)
228 {
229 int i = 0;
230 FILE * out = stdout;
231 if(format == BG_HELP_FORMAT_TEXI)
232 fprintf(out, "@table @i\n");
233 while(args[i].arg)
234 {
235 switch(format)
236 {
237 case BG_HELP_FORMAT_PLAIN:
238 case BG_HELP_FORMAT_TERM:
239 fprintf(out, " ");
240 print_bold(out, args[i].arg, format);
241
242 if(args[i].help_arg)
243 {
244 fprintf(out, " ");
245 print_italic(out, args[i].help_arg, format);
246 }
247 fprintf(out, "\n");
248 dump_string_term(out, args[i].help_string, 0, NULL, format);
249
250 break;
251 case BG_HELP_FORMAT_TEXI:
252 fprintf(out, "@item %s", args[i].arg);
253 if(args[i].help_arg)
254 {
255 fprintf(out, " ");
256 print_string(out, args[i].help_arg, format);
257 }
258 fprintf(out, "\n");
259 print_string(out, args[i].help_string, format);
260 fprintf(out, "@*\n");
261 break;
262 case BG_HELP_FORMAT_MAN:
263 print_bold(out, args[i].arg, format);
264 if(args[i].help_arg)
265 print_italic(out, args[i].help_arg, format);
266 fprintf(out, "\n");
267 fprintf(out, ".RS 2\n");
268 dump_string_term(out, args[i].help_string, 0, NULL, format);
269 fprintf(out, ".RE\n");
270
271 break;
272 }
273
274 if(args[i].parameters)
275 {
276 bg_cmdline_print_help_parameters(args[i].parameters, format);
277 }
278 fprintf(out, "\n");
279 i++;
280 }
281 if(format == BG_HELP_FORMAT_TEXI)
282 fprintf(out, "@end table\n");
283
284 }
285
286 static const bg_cmdline_arg_t auto_options[] =
287 {
288 {
289 .arg = "-help",
290 .help_string = TRS("Print this help message and exit"),
291 .callback = opt_help,
292 },
293 {
294 .arg = "-help-man",
295 .help_string = TRS("Print this help message as a manual page and exit"),
296 .callback = opt_help_man,
297 },
298 {
299 .arg = "-help-texi",
300 .help_string = TRS("Print this help message in texinfo format and exit"),
301 .callback = opt_help_texi,
302 },
303 {
304 .arg = "-version",
305 .help_string = TRS("Print version info and exit"),
306 .callback = opt_version,
307 },
308 { /* End of options */ }
309 };
310
bg_cmdline_print_help(char * argv0,bg_help_format_t format)311 void bg_cmdline_print_help(char * argv0, bg_help_format_t format)
312 {
313 int i;
314 char * tmp_string;
315
316 switch(format)
317 {
318 case BG_HELP_FORMAT_TERM:
319 case BG_HELP_FORMAT_PLAIN:
320 tmp_string = bg_sprintf(TRD(app_data->synopsis, app_data->package), argv0);
321 printf("Usage: %s\n\n", tmp_string);
322 free(tmp_string);
323 printf("%s\n", app_data->help_before);
324 i = 0;
325 while(app_data->args[i].name)
326 {
327 printf("%s\n\n", app_data->args[i].name);
328 print_help(app_data->args[i].args, format);
329 i++;
330 }
331 print_bold(stdout, "Generic options\n", format);
332 printf("\nThe following generic options are available for all gmerlin applications\n");
333 print_linebreak(stdout, format);
334 print_help(auto_options, format);
335
336 if(app_data->env)
337 {
338 print_bold(stdout, TR("Environment variables\n\n"), format);
339 i = 0;
340 while(app_data->env[i].name)
341 {
342 print_bold(stdout, app_data->env[i].name, format);
343 printf("\n");
344 dump_string_term(stdout, app_data->env[i].desc,
345 0, NULL, format);
346 i++;
347 print_linebreak(stdout, format);
348 }
349 }
350 if(app_data->files)
351 {
352 print_bold(stdout, TR("Files\n\n"), format);
353 i = 0;
354 while(app_data->files[i].name)
355 {
356 print_bold(stdout, app_data->files[i].name, format);
357 printf("\n");
358 dump_string_term(stdout, app_data->files[i].desc,
359 0, NULL, format);
360 print_linebreak(stdout, format);
361 i++;
362 }
363 }
364
365
366 break;
367 case BG_HELP_FORMAT_MAN:
368 {
369 char date_str[512];
370 struct tm brokentime;
371 time_t t;
372 char ** args;
373 char * string_uc;
374
375 time(&t);
376 localtime_r(&t, &brokentime);
377 strftime(date_str, 511, "%B %Y", &brokentime);
378
379 string_uc = bg_toupper(app_data->name);
380
381 printf(".TH %s 1 \"%s\" Gmerlin \"User Manuals\"\n", string_uc,
382 date_str);
383
384 free(string_uc);
385
386 printf(".SH NAME\n%s\n", app_data->name);
387 printf(".SH SYNOPSIS\n.B %s \n", app_data->name);
388 tmp_string = bg_strdup(NULL,
389 TRD(app_data->synopsis, app_data->package));
390
391 args = bg_strbreak(tmp_string, ' ');
392 i = 0;
393 while(args[i])
394 {
395 printf(".I %s\n", args[i]);
396 i++;
397 }
398
399 if(app_data->help_before)
400 printf(".SH DESCRIPTION\n%s\n", TRD(app_data->help_before, app_data->package));
401
402 i = 0;
403 while(app_data->args[i].name)
404 {
405 string_uc = bg_toupper(app_data->args[i].name);
406 printf(".SH %s\n\n", string_uc);
407 free(string_uc);
408 print_help(app_data->args[i].args, format);
409 i++;
410 }
411 printf(".SH GENERIC OPTIONS\nThe following generic options are available for all gmerlin applications\n\n");
412 print_help(auto_options, format);
413
414 if(app_data->env)
415 {
416 printf(TR(".SH ENVIRONMENT VARIABLES\n"));
417 i = 0;
418 while(app_data->env[i].name)
419 {
420 print_bold(stdout, app_data->env[i].name, format);
421 printf("\n");
422 printf(".RS 2\n");
423 dump_string_term(stdout, app_data->env[i].desc,
424 0, NULL, format);
425 printf(".RE\n");
426 i++;
427 }
428 }
429 if(app_data->files)
430 {
431 printf(TR(".SH FILES\n"));
432 i = 0;
433 while(app_data->files[i].name)
434 {
435 print_bold(stdout, app_data->files[i].name, format);
436 printf("\n");
437 printf(".RS 2\n");
438 dump_string_term(stdout, app_data->files[i].desc,
439 0, NULL, format);
440 printf(".RE\n");
441 print_linebreak(stdout, format);
442 i++;
443 }
444 }
445 }
446 break;
447 case BG_HELP_FORMAT_TEXI:
448 printf("@table @b\n");
449 printf("@item Synopsis\n");
450 printf("@b{%s} @i{%s}@*\n", app_data->name,
451 TRD(app_data->synopsis, app_data->package));
452 if(app_data->help_before)
453 {
454 printf("@item Description\n");
455 printf("%s@*\n", TRD(app_data->help_before, app_data->package));
456 }
457 i = 0;
458 while(app_data->args[i].name)
459 {
460 printf("@item %s\n", app_data->args[i].name);
461 print_help(app_data->args[i].args, format);
462 i++;
463 }
464 printf("@item Generic options\n");
465 printf("The following generic options are available for all gmerlin applications@*\n");
466 print_help(auto_options, format);
467
468 if(app_data->env)
469 {
470 printf(TR("@item Environment variables\n"));
471 printf("@table @env\n");
472 i = 0;
473 while(app_data->env[i].name)
474 {
475 printf("@item %s\n", app_data->env[i].name);
476 printf("%s@*\n", TRD(app_data->env[i].desc, app_data->package));
477 i++;
478 }
479 printf("@end table\n");
480 }
481
482 if(app_data->files)
483 {
484 printf(TR("@item Files\n"));
485 printf("@table @file\n");
486 i = 0;
487 while(app_data->files[i].name)
488 {
489 printf("@item %s\n", app_data->files[i].name);
490 printf("%s@*\n", TRD(app_data->files[i].desc, app_data->package));
491 i++;
492 }
493 printf("@end table\n");
494 }
495 printf("@end table\n");
496 break;
497 }
498
499 }
500
501
opt_help(void * data,int * argc,char *** argv,int arg)502 static void opt_help(void * data, int * argc, char *** argv, int arg)
503 {
504 if(isatty(fileno(stdout)))
505 bg_cmdline_print_help((*argv)[0], BG_HELP_FORMAT_TERM);
506 else
507 bg_cmdline_print_help((*argv)[0], BG_HELP_FORMAT_PLAIN);
508 exit(0);
509 }
510
opt_help_man(void * data,int * argc,char *** argv,int arg)511 static void opt_help_man(void * data, int * argc, char *** argv, int arg)
512 {
513 bg_cmdline_print_help((*argv)[0], BG_HELP_FORMAT_MAN);
514 exit(0);
515 }
516
opt_help_texi(void * data,int * argc,char *** argv,int arg)517 static void opt_help_texi(void * data, int * argc, char *** argv, int arg)
518 {
519 bg_cmdline_print_help((*argv)[0], BG_HELP_FORMAT_TEXI);
520 exit(0);
521 }
522
opt_version(void * data,int * argc,char *** argv,int arg)523 static void opt_version(void * data, int * argc, char *** argv, int arg)
524 {
525 print_version(app_data);
526 exit(0);
527 }
528
529
530 /* */
531
bg_cmdline_remove_arg(int * argc,char *** _argv,int arg)532 void bg_cmdline_remove_arg(int * argc, char *** _argv, int arg)
533 {
534 char ** argv = *_argv;
535 /* Move the upper args down */
536 if(arg < *argc - 1)
537 memmove(argv + arg, argv + arg + 1,
538 (*argc - arg - 1) * sizeof(*argv));
539 (*argc)--;
540 }
541
542
543
cmdline_parse(const bg_cmdline_arg_t * args,int * argc,char *** _argv,void * callback_data,int parse_auto)544 static void cmdline_parse(const bg_cmdline_arg_t * args,
545 int * argc, char *** _argv,
546 void * callback_data,
547 int parse_auto)
548 {
549 int found;
550 int i, j;
551 char ** argv = *_argv;
552
553 i = 1;
554
555 if(parse_auto)
556 {
557 cmdline_parse(auto_options, argc, _argv, NULL, 0);
558 }
559
560 if(!args)
561 return;
562
563 while(i < *argc)
564 {
565 j = 0;
566 found = 0;
567
568 if(!strcmp(argv[i], "--"))
569 break;
570
571 while(args[j].arg)
572 {
573 if(!strcmp(args[j].arg, argv[i]))
574 {
575 bg_cmdline_remove_arg(argc, _argv, i);
576 if(args[j].callback)
577 args[j].callback(callback_data, argc, _argv, i);
578 else if(args[j].parameters)
579 {
580 }
581
582 found = 1;
583 break;
584 }
585 else
586 j++;
587 }
588 if(!found)
589 i++;
590 }
591 }
592
bg_cmdline_parse(bg_cmdline_arg_t * args,int * argc,char *** _argv,void * callback_data)593 void bg_cmdline_parse(bg_cmdline_arg_t * args, int * argc, char *** _argv,
594 void * callback_data)
595 {
596 cmdline_parse(args, argc, _argv, callback_data, 1);
597 }
598
599
bg_cmdline_get_locations_from_args(int * argc,char *** _argv)600 char ** bg_cmdline_get_locations_from_args(int * argc, char *** _argv)
601 {
602 char ** ret;
603 int seen_dashdash;
604 char ** argv;
605 int i, index;
606 int num_locations = 0;
607 argv = *_argv;
608
609 /* Count the locations */
610
611 for(i = 1; i < *argc; i++)
612 {
613 if(!strcmp(argv[i], "--"))
614 {
615 num_locations += *argc - 1 - i;
616 break;
617 }
618 else if(argv[i][0] != '-')
619 num_locations++;
620 }
621
622 if(!num_locations)
623 return NULL;
624
625 /* Allocate return value */
626
627 ret = calloc(num_locations + 1, sizeof(*ret));
628
629 i = 1;
630 index = 0;
631 seen_dashdash = 0;
632
633 while(i < *argc)
634 {
635 if(seen_dashdash || (argv[i][0] != '-'))
636 {
637 ret[index++] = argv[i];
638 bg_cmdline_remove_arg(argc, _argv, i);
639 }
640 else if(!strcmp(argv[i], "--"))
641 {
642 seen_dashdash = 1;
643 bg_cmdline_remove_arg(argc, _argv, i);
644 }
645 else
646 {
647 i++;
648 }
649 }
650 return ret;
651 }
652
653
bg_cmdline_apply_options(bg_cfg_section_t * section,bg_set_parameter_func_t set_parameter,void * data,const bg_parameter_info_t * parameters,const char * option_string)654 int bg_cmdline_apply_options(bg_cfg_section_t * section,
655 bg_set_parameter_func_t set_parameter,
656 void * data,
657 const bg_parameter_info_t * parameters,
658 const char * option_string)
659 {
660 if(!bg_cfg_section_set_parameters_from_string(section,
661 parameters,
662 option_string))
663 return 0;
664 /* Now, apply the section */
665 if(set_parameter)
666 bg_cfg_section_apply(section, parameters, set_parameter, data);
667 return 1;
668 }
669
670
671
print_help_parameters(int indent,const bg_parameter_info_t * parameters,bg_help_format_t format)672 static void print_help_parameters(int indent,
673 const bg_parameter_info_t * parameters,
674 bg_help_format_t format)
675 {
676 int i = 0;
677 int j;
678 FILE * out = stdout;
679
680 int pos;
681
682 char time_string[GAVL_TIME_STRING_LEN];
683 char * tmp_string;
684
685 const char * translation_domain = NULL;
686
687 indent += 2;
688 if(format == BG_HELP_FORMAT_MAN)
689 fprintf(out, ".RS 2\n");
690 else if(format == BG_HELP_FORMAT_TEXI)
691 fprintf(out, "@table @r\n");
692
693 if(!indent)
694 {
695 do_indent(out, indent+2, format);
696
697 fprintf(out, TR("Supported options:\n\n"));
698 }
699
700 while(parameters[i].name)
701 {
702 if(parameters[i].gettext_domain)
703 translation_domain = parameters[i].gettext_domain;
704 if(parameters[i].gettext_directory)
705 bg_bindtextdomain(translation_domain, parameters[i].gettext_directory);
706
707 if((parameters[i].type == BG_PARAMETER_SECTION) ||
708 (parameters[i].flags & BG_PARAMETER_HIDE_DIALOG))
709 {
710 i++;
711 continue;
712 }
713 pos = 0;
714
715 if(format == BG_HELP_FORMAT_MAN)
716 {
717 do_indent(out, indent+2, format);
718 fprintf(out, ".BR ");
719
720 // pos += fprintf(out, spaces);
721 // pos += fprintf(out, " ");
722
723 if(parameters[i].opt)
724 {
725 fprintf(out, "%s", parameters[i].opt);
726 pos += strlen(parameters[i].opt);
727 }
728 else
729 {
730 fprintf(out, "%s", parameters[i].name);
731 pos += strlen(parameters[i].name);
732 }
733 fprintf(out, " \"=");
734 }
735 else if(format == BG_HELP_FORMAT_TEXI)
736 {
737 fprintf(out, "@item ");
738
739 pos += indent+2;
740
741 if(parameters[i].opt)
742 {
743 print_bold(out, parameters[i].opt, format);
744 pos += strlen(parameters[i].opt);
745 }
746 else
747 {
748 print_bold(out, parameters[i].name, format);
749 pos += strlen(parameters[i].name);
750 }
751 fprintf(out, "=");
752 }
753 else
754 {
755 do_indent(out, indent+2, format);
756 pos += indent+2;
757
758 if(parameters[i].opt)
759 {
760 print_bold(out, parameters[i].opt, format);
761 pos += strlen(parameters[i].opt);
762 }
763 else
764 {
765 print_bold(out, parameters[i].name, format);
766 pos += strlen(parameters[i].name);
767 }
768 fprintf(out, "=");
769 }
770
771 switch(parameters[i].type)
772 {
773 case BG_PARAMETER_SECTION:
774 case BG_PARAMETER_BUTTON:
775 break;
776 case BG_PARAMETER_CHECKBUTTON:
777 tmp_string = bg_sprintf(TR("[1|0] (default: %d)"), parameters[i].val_default.val_i);
778 print_string(out, tmp_string, format);
779 free(tmp_string);
780 if(format == BG_HELP_FORMAT_MAN)
781 fprintf(out, "\"");
782 print_linebreak(out, format);
783 break;
784 case BG_PARAMETER_INT:
785 case BG_PARAMETER_SLIDER_INT:
786 pos += fprintf(out, TR("<number> ("));
787 if(parameters[i].val_min.val_i < parameters[i].val_max.val_i)
788 {
789 pos += fprintf(out, "%d..%d, ",
790 parameters[i].val_min.val_i, parameters[i].val_max.val_i);
791 }
792 fprintf(out, TR("default: %d)"), parameters[i].val_default.val_i);
793
794 if(format == BG_HELP_FORMAT_MAN)
795 fprintf(out, "\"");
796 print_linebreak(out, format);
797 break;
798 case BG_PARAMETER_SLIDER_FLOAT:
799 case BG_PARAMETER_FLOAT:
800 pos += fprintf(out, TR("<number> ("));
801 if(parameters[i].val_min.val_f < parameters[i].val_max.val_f)
802 {
803 tmp_string = bg_sprintf("%%.%df..%%.%df, ",
804 parameters[i].num_digits,
805 parameters[i].num_digits);
806 pos += fprintf(out, tmp_string,
807 parameters[i].val_min.val_f, parameters[i].val_max.val_f);
808 free(tmp_string);
809 }
810 tmp_string =
811 bg_sprintf(TR("default: %%.%df)"),
812 parameters[i].num_digits);
813 fprintf(out, tmp_string,
814 parameters[i].val_default.val_f);
815 free(tmp_string);
816
817 if(format == BG_HELP_FORMAT_MAN)
818 fprintf(out, "\"");
819 print_linebreak(out, format);
820
821 break;
822 case BG_PARAMETER_STRING:
823 case BG_PARAMETER_FONT:
824 case BG_PARAMETER_DEVICE:
825 case BG_PARAMETER_FILE:
826 case BG_PARAMETER_DIRECTORY:
827 pos += fprintf(out, TR("<string>"));
828 if(parameters[i].val_default.val_str)
829 {
830 tmp_string = bg_sprintf(TR(" (Default: %s)"), parameters[i].val_default.val_str);
831 print_string(out, tmp_string, format);
832 free(tmp_string);
833 }
834 if(format == BG_HELP_FORMAT_MAN)
835 fprintf(out, "\"");
836 print_linebreak(out, format);
837
838 break;
839 case BG_PARAMETER_STRING_HIDDEN:
840 pos += fprintf(out, TR("<string>"));
841
842 if(format == BG_HELP_FORMAT_MAN)
843 fprintf(out, "\"");
844 print_linebreak(out, format);
845 break;
846 case BG_PARAMETER_STRINGLIST:
847 pos += fprintf(out, TR("<string>"));
848 if(format == BG_HELP_FORMAT_MAN)
849 fprintf(out, "\"");
850 print_linebreak(out, format);
851
852 j = 0;
853
854 pos = 0;
855 do_indent(out, indent+2, format);
856 pos += indent+2;
857 pos += fprintf(out, TR("Supported strings: "));
858
859 while(parameters[i].multi_names[j])
860 {
861 if(j) pos += fprintf(out, " ");
862
863 if(pos + strlen(parameters[i].multi_names[j]+1) > MAX_COLS)
864 {
865 if((format == BG_HELP_FORMAT_TERM) || (format == BG_HELP_FORMAT_PLAIN))
866 fprintf(out, "\n");
867 pos = 0;
868 do_indent(out, indent+2, format);
869 pos += indent+2;
870 }
871
872 pos += fprintf(out, "%s", parameters[i].multi_names[j]);
873 j++;
874 }
875 print_linebreak(out, format);
876 do_indent(out, indent+2, format);
877 pos += indent+2;
878
879 tmp_string = bg_sprintf(TR("Default: %s"), parameters[i].val_default.val_str);
880 print_string(out, tmp_string, format);
881 free(tmp_string);
882 print_linebreak(out, format);
883
884 break;
885 case BG_PARAMETER_COLOR_RGB:
886 fprintf(out, TR("<r>,<g>,<b> (default: %.3f,%.3f,%.3f)"),
887 parameters[i].val_default.val_color[0],
888 parameters[i].val_default.val_color[1],
889 parameters[i].val_default.val_color[2]);
890 if(format == BG_HELP_FORMAT_MAN)
891 fprintf(out, "\"");
892 print_linebreak(out, format);
893
894 do_indent(out, indent+2, format);
895 pos += indent+2;
896
897 fprintf(out, TR("<r>, <g> and <b> are in the range 0.0..1.0"));
898 if(format != BG_HELP_FORMAT_MAN)
899 fprintf(out, "\n");
900 else
901 fprintf(out, "\n.P\n");
902 break;
903 case BG_PARAMETER_COLOR_RGBA:
904 fprintf(out, TR("<r>,<g>,<b>,<a> (default: %.3f,%.3f,%.3f,%.3f)"),
905 parameters[i].val_default.val_color[0],
906 parameters[i].val_default.val_color[1],
907 parameters[i].val_default.val_color[2],
908 parameters[i].val_default.val_color[3]);
909 if(format == BG_HELP_FORMAT_MAN)
910 fprintf(out, "\"");
911 print_linebreak(out, format);
912
913 do_indent(out, indent+2, format);
914 pos += indent+2;
915
916 fprintf(out, TR("<r>, <g>, <b> and <a> are in the range 0.0..1.0"));
917 if(format != BG_HELP_FORMAT_MAN)
918 fprintf(out, "\n");
919 else
920 fprintf(out, "\n.P\n");
921 break;
922 case BG_PARAMETER_MULTI_MENU:
923 print_string(out, TR("option[{suboptions}]"), format);
924 if(format == BG_HELP_FORMAT_MAN)
925 fprintf(out, "\"");
926 print_linebreak(out, format);
927 pos = 0;
928
929 do_indent(out, indent+2, format);
930 pos += indent+2;
931
932 pos += fprintf(out, TR("Supported options: "));
933 j = 0;
934
935 if(parameters[i].multi_names)
936 {
937 while(parameters[i].multi_names[j])
938 {
939 if(j) pos += fprintf(out, " ");
940
941 if(pos + strlen(parameters[i].multi_names[j]) > MAX_COLS)
942 {
943 if(format != BG_HELP_FORMAT_MAN)
944 fprintf(out, "\n");
945 pos = 0;
946 do_indent(out, indent+2, format);
947 pos += indent+2;
948 }
949 pos += fprintf(out, "%s", parameters[i].multi_names[j]);
950 j++;
951 }
952 }
953 else
954 pos += fprintf(out, TR("<None>"));
955
956 print_linebreak(out, format);
957
958 do_indent(out, indent+2, format);
959 pos += indent+2;
960 fprintf(out, TR("Default: %s"), parameters[i].val_default.val_str);
961
962 print_linebreak(out, format);
963 break;
964 case BG_PARAMETER_MULTI_LIST:
965 case BG_PARAMETER_MULTI_CHAIN:
966 print_string(out, TR("{option[{suboptions}][:option[{suboptions}]...]}"), format);
967
968 if(format == BG_HELP_FORMAT_MAN)
969 fprintf(out, "\"");
970
971 print_linebreak(out, format);
972
973 pos = 0;
974
975 do_indent(out, indent+2, format);
976 pos += indent+2;
977
978 pos += fprintf(out, TR("Supported options: "));
979 j = 0;
980 while(parameters[i].multi_names[j])
981 {
982 if(j) pos += fprintf(out, " ");
983
984 if(pos + strlen(parameters[i].multi_names[j]+1) > MAX_COLS)
985 {
986 fprintf(out, "\n");
987 pos = 0;
988 do_indent(out, indent+4, format);
989 pos += indent+4;
990 }
991 pos += fprintf(out, "%s", parameters[i].multi_names[j]);
992 j++;
993 }
994 fprintf(out, "\n\n");
995
996 break;
997 case BG_PARAMETER_TIME:
998 print_string(out, TR("{[[HH:]MM:]SS} ("), format);
999 if(parameters[i].val_min.val_time < parameters[i].val_max.val_time)
1000 {
1001 gavl_time_prettyprint(parameters[i].val_min.val_time, time_string);
1002 fprintf(out, "%s..", time_string);
1003
1004 gavl_time_prettyprint(parameters[i].val_max.val_time, time_string);
1005 fprintf(out, "%s, ", time_string);
1006 }
1007 gavl_time_prettyprint(parameters[i].val_default.val_time, time_string);
1008 fprintf(out, TR("default: %s)"), time_string);
1009
1010 if(format == BG_HELP_FORMAT_MAN)
1011 fprintf(out, "\"");
1012 print_linebreak(out, format);
1013
1014 do_indent(out, indent+2, format);
1015 pos += indent+2;
1016 fprintf(out, TR("Seconds can be fractional (i.e. with decimal point)\n"));
1017 break;
1018 case BG_PARAMETER_POSITION:
1019 fprintf(out, TR("<x>,<y> (default: %.3f,%.3f)"),
1020 parameters[i].val_default.val_pos[0],
1021 parameters[i].val_default.val_pos[1]);
1022 if(format == BG_HELP_FORMAT_MAN)
1023 fprintf(out, "\"");
1024 print_linebreak(out, format);
1025
1026 do_indent(out, indent+2, format);
1027 pos += indent+2;
1028
1029 fprintf(out, TR("<r>, <g> and <b> are in the range 0.0..1.0"));
1030 if(format != BG_HELP_FORMAT_MAN)
1031 fprintf(out, "\n");
1032 else
1033 fprintf(out, "\n.P\n");
1034 break;
1035
1036
1037 }
1038
1039 do_indent(out, indent+2, format);
1040 pos += indent+2;
1041
1042 fprintf(out, "%s", TR_DOM(parameters[i].long_name));
1043
1044 print_linebreak(out, format);
1045
1046 if(parameters[i].help_string)
1047 {
1048 dump_string_term(out, parameters[i].help_string, indent, translation_domain, format);
1049 print_linebreak(out, format);
1050 }
1051
1052 /* Print suboptions */
1053
1054 if(parameters[i].multi_parameters)
1055 {
1056 j = 0;
1057 while(parameters[i].multi_names[j])
1058 {
1059 if(parameters[i].multi_parameters[j])
1060 {
1061 do_indent(out, indent+2, format);
1062 pos += indent+2;
1063 // print_linebreak(out, format);
1064
1065 if(parameters[i].type == BG_PARAMETER_MULTI_MENU)
1066 {
1067 if(parameters[i].opt)
1068 tmp_string = bg_sprintf(TR("Suboptions for %s=%s"),
1069 parameters[i].opt,parameters[i].multi_names[j]);
1070 else
1071 tmp_string = bg_sprintf(TR("Suboptions for %s=%s"),
1072 parameters[i].name,parameters[i].multi_names[j]);
1073 }
1074 else
1075 {
1076 tmp_string = bg_sprintf(TR("Suboptions for %s"),
1077 parameters[i].multi_names[j]);
1078 }
1079 print_bold(out, tmp_string, format);
1080 free(tmp_string);
1081 print_linebreak(out, format);
1082
1083 // print_linebreak(out, format);
1084 // print_linebreak(out, format);
1085 print_help_parameters(indent+2, parameters[i].multi_parameters[j], format);
1086 }
1087 j++;
1088 }
1089 }
1090
1091 i++;
1092 }
1093
1094 if(format == BG_HELP_FORMAT_MAN)
1095 fprintf(out, ".RE\n");
1096 else if(format == BG_HELP_FORMAT_TEXI)
1097 fprintf(out, "@end table\n");
1098
1099 }
1100
bg_cmdline_print_help_parameters(const bg_parameter_info_t * parameters,bg_help_format_t format)1101 void bg_cmdline_print_help_parameters(const bg_parameter_info_t * parameters,
1102 bg_help_format_t format)
1103 {
1104 print_help_parameters(0, parameters, format);
1105 }
1106
bg_cmdline_init(const bg_cmdline_app_data_t * data)1107 void bg_cmdline_init(const bg_cmdline_app_data_t * data)
1108 {
1109 app_data = data;
1110 }
1111