Overview

Request 4493 (accepted)

- Update to version 0.35.2
* Fixed set_chapters not having exec bit set
* Fixed grep for libav filters
* Some python3 fixes
* Fixed scope problem that only showed up on freebsd for some
reason.
* Fixed imagemagick spumux buttons for IM-6.9.1-x.
* Make ffmpeg the default encoder when both ffmpeg and avconv
are present.

Submit package home:Aloysius:branches:Multimedia / tovid to package Multimedia / tovid

tovid.changes Changed
x
 
1
@@ -1,4 +1,17 @@
2
 -------------------------------------------------------------------
3
+Fri May 24 13:24:31 UTC 2019 - Luigi Baldoni <aloisio@gmx.com>
4
+
5
+- Update to version 0.35.2
6
+  * Fixed set_chapters not having exec bit set
7
+  * Fixed grep for libav filters
8
+  * Some python3 fixes
9
+  * Fixed scope problem that only showed up on freebsd for some
10
+    reason.
11
+  * Fixed imagemagick spumux buttons for IM-6.9.1-x.
12
+  * Make ffmpeg the default encoder when both ffmpeg and avconv
13
+    are present.
14
+
15
+-------------------------------------------------------------------
16
 Mon Apr  6 19:29:20 UTC 2015 - aloisio@gmx.com
17
 
18
 - Version 0.35.0
19
tovid.spec Changed
97
 
1
@@ -1,6 +1,7 @@
2
-# vim: set ts=4 sw=4 et:
3
 #
4
-# Copyright (c) 2015 Luigi Baldoni <aloisio@gmx.com>
5
+# spec file for package tovid
6
+#
7
+# Copyright (c) 2015-2019 Luigi Baldoni <aloisio@gmx.com>
8
 # Copyright (c) 2005-2010 oc2pus
9
 #
10
 # All modifications and additions to the file contributed by third parties
11
@@ -12,24 +13,24 @@
12
 # license that conforms to the Open Source Definition (Version 1.9)
13
 # published by the Open Source Initiative.
14
 
15
-# Please submit bugfixes or comments to packman@links2linux.de
16
+# Please submit bugfixes or comments via https://bugs.links2linux.org/
17
+#
18
 
19
 
20
-%{!?python_sitelib:  %global python_sitelib  %(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")}
21
-%{!?python_sitearch: %global python_sitearch %(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
22
 Name:           tovid
23
-Version:        0.35.0
24
+Version:        0.35.2
25
 Release:        0
26
 Summary:        Video conversion and DVD authoring tools
27
-License:        GPL-2.0+
28
+License:        GPL-2.0-or-later
29
 Group:          Productivity/Multimedia/Video/Editors and Convertors
30
-Url:            http://tovid.wikia.com/wiki/Tovid_Wiki
31
-Source:         https://github.com/tovid-suite/tovid/releases/download/v0.35.0/tovid-%{version}.tar.gz
32
+URL:            http://tovid.wikia.com/wiki/Tovid_Wiki
33
+Source:         https://github.com/tovid-suite/tovid/releases/download/%{version}/tovid-%{version}.tar.gz
34
 BuildRequires:  hicolor-icon-theme
35
 BuildRequires:  python-devel
36
 BuildRequires:  python-setuptools
37
 BuildRequires:  txt2tags
38
 BuildRequires:  update-desktop-files
39
+Requires:       /usr/bin/mkisofs
40
 Requires:       ImageMagick >= 6.0
41
 Requires:       MPlayer
42
 Requires:       bc
43
@@ -39,7 +40,6 @@
44
 Requires:       ffmpeg
45
 Requires:       lsdvd
46
 Requires:       mjpegtools
47
-Requires:       /usr/bin/mkisofs
48
 Requires:       normalize
49
 Requires:       python-base >= %{py_ver}
50
 Requires:       python-tk
51
@@ -48,11 +48,7 @@
52
 Requires:       tk
53
 Recommends:     libdvdcss2
54
 Recommends:     transcode
55
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
56
-%py_requires
57
-%if 0%{?suse_version} > 1110
58
 BuildArch:      noarch
59
-%endif
60
 
61
 %description
62
 tovid is a suite of utilities designed to make DVD
63
@@ -64,6 +60,14 @@
64
 
65
 %prep
66
 %setup -q
67
+# fix shebang
68
+sed -i 's|^#!.*|#!%{_bindir}/bash|'   \
69
+ src/idvid src/makedvd src/makempg    \
70
+ src/todisc src/todisc-fade-routine   \
71
+ src/tovid-init.in
72
+sed -i 's|^#!.*|#!%{_bindir}/python|' \
73
+ src/set_chapters src/titleset-wizard \
74
+ src/todiscgui src/tovid-stats
75
 
76
 %build
77
 python setup.py build
78
@@ -82,8 +86,8 @@
79
 done
80
 
81
 %files
82
-%defattr(-,root,root)
83
-%doc AUTHORS ChangeLog COPYING README
84
+%license COPYING
85
+%doc AUTHORS ChangeLog README
86
 %{_bindir}/tovid
87
 %{python_sitelib}/libtovid
88
 %{python_sitelib}/tovid-%{version}*
89
@@ -93,6 +97,6 @@
90
 %{_datadir}/icons/*/*/apps/tovid.png
91
 %{_datadir}/icons/*/*/apps/titleset-wizard.png
92
 %{_datadir}/icons/*/scalable/apps/*.svg
93
-%doc %{_mandir}/man1/tovid.1%{ext_man}
94
+%{_mandir}/man1/tovid.1%{?ext_man}
95
 
96
 %changelog
97
tovid-0.35.0.tar.gz/docs/src/en/tovid.html Deleted
1920
 
1
@@ -1,1918 +0,0 @@
2
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
3
-<HTML>
4
-<HEAD>
5
-<META NAME="generator" CONTENT="http://txt2tags.org">
6
-<TITLE>tovid manual</TITLE>
7
-</HEAD><BODY BGCOLOR="white" TEXT="black">
8
-<CENTER>
9
-<H1>tovid manual</H1>
10
-</CENTER>
11
-
12
-<P></P>
13
-<HR NOSHADE SIZE=1>
14
-<P></P>
15
-
16
-  <UL>
17
-  <LI><A HREF="#toc1">Name</A>
18
-  <LI><A HREF="#toc2">Description</A>
19
-  <LI><A HREF="#toc3">Usage</A>
20
-  <LI><A HREF="#toc4">Configuration</A>
21
-  <LI><A HREF="#toc5">Command:gui</A>
22
-  <LI><A HREF="#toc6">Usage</A>
23
-  <LI><A HREF="#toc7">Command:titlesets</A>
24
-  <LI><A HREF="#toc8">Command:disc</A>
25
-    <UL>
26
-    <LI><A HREF="#toc9">Usage</A>
27
-    <LI><A HREF="#toc10">General Options</A>
28
-    <LI><A HREF="#toc11">Menu style</A>
29
-    <LI><A HREF="#toc12">Thumbnail style</A>
30
-    <LI><A HREF="#toc13">Slideshows</A>
31
-    <LI><A HREF="#toc14">Burning the disc</A>
32
-    <LI><A HREF="#toc15">Advanced usage</A>
33
-    <LI><A HREF="#toc16">Menu Style</A>
34
-    <LI><A HREF="#toc17">Thumbnail Style</A>
35
-    <LI><A HREF="#toc18">Dvdauthor options</A>
36
-    <LI><A HREF="#toc19">Usage notes</A>
37
-    </UL>
38
-  <LI><A HREF="#toc20">Command:mpg</A>
39
-    <UL>
40
-    <LI><A HREF="#toc21">Usage</A>
41
-    <LI><A HREF="#toc22">Basic options</A>
42
-    <LI><A HREF="#toc23">Advanced options</A>
43
-    </UL>
44
-  <LI><A HREF="#toc24">Command:id</A>
45
-    <UL>
46
-    <LI><A HREF="#toc25">Usage</A>
47
-    <LI><A HREF="#toc26">Options</A>
48
-    <LI><A HREF="#toc27">Examples</A>
49
-    </UL>
50
-  <LI><A HREF="#toc28">Command:dvd</A>
51
-    <UL>
52
-    <LI><A HREF="#toc29">Usage</A>
53
-    <LI><A HREF="#toc30">Options</A>
54
-    </UL>
55
-  <LI><A HREF="#toc31">Command:chapters</A>
56
-    <UL>
57
-    <LI><A HREF="#toc32">Examples</A>
58
-    </UL>
59
-  <LI><A HREF="#toc33">CONTACT</A>
60
-  </UL>
61
-
62
-<P></P>
63
-<HR NOSHADE SIZE=1>
64
-<P></P>
65
-
66
-<A NAME="toc1"></A>
67
-<H1>Name</H1>
68
-
69
-<P>
70
-tovid: Make DVDs from video files
71
-</P>
72
-
73
-<A NAME="toc2"></A>
74
-<H1>Description</H1>
75
-
76
-<P>
77
-<B>tovid</B> is a command-line tool for creating DVDs. It can encode your video
78
-files to DVD-compliant MPEG format, generate simple or complex DVD menus,
79
-author and burn a ready-to-watch DVD, with just a few shell commands. A
80
-graphical interface is also provided to make the process even easier.
81
-</P>
82
-<P>
83
-<B>NOTE</B>: As of tovid 0.35, the legacy scripts <B>makemenu</B> and <B>makexml</B>
84
-have been removed and no longer appear in this manpage.
85
-All of their functions and more can be done with the 'tovid disc' command,
86
-(todisc script). See <B>Command:disc</B> and the <A HREF="http://tovid.wikia.com">wiki</A>
87
-for more info.
88
-</P>
89
-<P>
90
-Also note that as of tovid 0.32, this is the only manual page provided by tovid.
91
-There is now a single executable frontend to all functionality in the suite, so
92
-if you were expecting to find manpages for <B>todisc</B>, <B>idvid</B>, <B>makempg</B>
93
-and their kin, they can all be found in the <B>tovid</B> manpage you are reading now.
94
-And yes, this makes for a pretty large manual page. If you are viewing this
95
-manpage from the command-line <B>man</B> utility, which normally pages through the
96
-<B>less</B> utility, you can skip to a section by searching with the <B>/</B> key,
97
-followed by a <B>^</B> to match the given section name. For example, to skip to
98
-the <B>mpg</B> command, type <B>/^Command:mpg</B>. See <B>man less</B> for more on how
99
-to navigate.
100
-</P>
101
-
102
-<A NAME="toc3"></A>
103
-<H1>Usage</H1>
104
-
105
-<P>
106
-<B>tovid</B> <I>COMMAND</I> [<I>OPTIONS</I>]
107
-</P>
108
-<P>
109
-Where <I>COMMAND</I> is one of the following:
110
-</P>
111
-<P>
112
-    Main Commands
113
-</P>
114
-
115
-<DL>
116
-<DT><B>disc</B></DT><DD>
117
-    Encode, make menus, author, burn. (was <B>todisc</B>. See <B>Command:disc</B>)
118
-<DT><B>gui</B></DT><DD>
119
-    Start the tovid GUI (was <B>todiscgui</B>. See <B>Command:gui</B>)
120
-<DT><B>titlesets</B></DT><DD>
121
-    A GUI wizard for multiple titlesets. (new: See <B>Command:titlesets</B>)
122
-</DL>
123
-
124
-<P>
125
-    Helper Commands
126
-</P>
127
-
128
-<DL>
129
-<DT><B>mpg</B></DT><DD>
130
-    Encode videos to MPEG format (was <B>tovid</B>. See <B>Command:mpg</B>)
131
-<DT><B>dvd</B></DT><DD>
132
-    Author and/or burn a DVD (was <B>makedvd</B>. See <B>Command:dvd</B>)
133
-<DT><B>id</B></DT><DD>
134
-    Identify one or more video files (was <B>idvid</B>. See <B>Command:id</B>)
135
-<DT><B>chapters</B></DT><DD>
136
-    A GUI using mplayer for setting chapter points.  It will return a string of
137
-    chapter points to the terminal, in a format recognized by 'tovid disc'
138
-    (todisc) or by 'tovid gui', for the  <B>-chapters</B> option.
139
-</DL>
140
-
141
-<P>
142
-The <I>OPTIONS</I> differ for each command; run <B>tovid &lt;command&gt;</B> with no
143
-further arguments to get help on a command, and what options it expects.
144
-</P>
145
-
146
-<A NAME="toc4"></A>
147
-<H1>Configuration</H1>
148
-
149
-<P>
150
-Two configuration files are created the first time you run tovid:
151
-</P>
152
-
153
-<DL>
154
-<DT><B>~/.tovid/preferences</B></DT><DD>
155
-    Defines working directory for all scripts.
156
-    You can define the output directory for makempg here.
157
-    The 'ffmpeg' executable can be set here: ffmpeg or avconv (TOVID_FFMPEG)
158
-<DT><B>~/.tovid/tovid.ini</B></DT><DD>
159
-    Includes command-line options that should be passed to the various
160
-    <B>tovid</B> sub-commands.  Note: each sub-command has its own section,
161
-    starting with the line [sub-command], for example:
162
-
163
-<PRE>
164
-      [disc]
165
-      ; -no-warn
166
-      -static
167
-      -no-ask
168
-</PRE>
169
-
170
-</DL>
171
-
172
-<P>
173
-Edit these files if you wish to change your configuration.
174
-</P>
175
-<P>
176
-The following environment variables are also honoured:
177
-</P>
178
-
179
-<PRE>
180
-      TOVID_HOME (directory containing preferences: ~/.tovid)
181
-      TOVID_WORKING_DIR (working directory for all scripts).
182
-      TOVID_OUTPUT_DIR (output directory for the makempg script).
183
-      TOVID_FFMPEG_CMD (the 'ffmpeg' executable to use: ffmpeg or avconv)
184
-</PRE>
185
-
186
-<P>
187
-These will override 'TOVID_HOME', 'WORKING_DIR', 'OUTPUT_DIR',
188
-and 'TOVID_FFMPEG' if set in ~/.tovid/preferences.
189
-</P>
190
-
191
-<A NAME="toc5"></A>
192
-<H1>Command:gui</H1>
193
-
194
-<A NAME="toc6"></A>
195
-<H1>Usage</H1>
196
-
197
-<P>
198
-<B>tovid gui</B> [<I>OPTIONS</I>]
199
-</P>
200
-<P>
201
-<B>tovid gui</B> starts the graphical user interface (GUI) for tovid. This is
202
-the easiest way to start creating DVDs with tovid. The optional arguments
203
-<I>OPTIONS</I> are any option used by todisc ('tovid disc') which will save
204
-entering it manually, OR the full path to a saved script from the GUI.
205
-You can also combine these, but the script must be the FIRST option
206
-directly after <B>tovid gui</B> .  (This option to save the contents of your
207
-project allows you to use it as a bash script later, or to reload the
208
-project to continue working with it at another time.)
209
-</P>
210
-<P>
211
-<B>tovid gui</B> will also take the option <B>--position</B>, which denotes the
212
-screen position that the GUI will start at, in the form '+X+Y', similar to
213
-this part of the Xorg -geometry string.
214
-</P>
215
-<P>
216
-All help is integrated in the form of tooltips.  You can also see
217
-**Command:disc ** for more detail about the options.  Note: if you wish to use
218
-a GUI to make multiple titlesets on the same DVD use <B>*tovid titlesets*</B>,
219
-which is a wizard that uses the the 'tovid gui. See <B>*Command:titlesets*</B>.
220
-</P>
221
-<P>
222
-Please note that although the interface may seem complex with so many options,
223
-you can create a fully functional DVD with only a few options on the opening
224
-tab of the GUI (select video files and an output name).
225
-</P>
226
-
227
-<A NAME="toc7"></A>
228
-<H1>Command:titlesets</H1>
229
-
230
-<P>
231
-<B>tovid titlesets</B> will assist in making a DVD with multiple titlesets.  It can
232
-be started without any options, or you can feed it the path to a saved titleset
233
-script as an option.  The option to save a script is also useful as the resulting
234
-script can be run later from a terminal.
235
-</P>
236
-
237
-<A NAME="toc8"></A>
238
-<H1>Command:disc</H1>
239
-
240
-<P>
241
-<B>tovid disc</B> creates a DVD file-system with optional menus, from a list of
242
-multimedia video files and their titles.  As todisc can function as a master
243
-script, calling other scripts as it needs them, it is the easiest command line
244
-program for creating a DVD from start to finish, including automatically
245
-converting non-compliant videos and prompting to burn at completion.  It can do
246
-animated menus, static thumbnail menus, text-only menus, or author with no menu.
247
-In addition, it can do slideshows, using images as input, and even combine
248
-slideshows with videos.  It supports sub-menus for chapter breaks,
249
-configurable menu style, animated backgrounds and transparency effects.
250
-From simple (no menu) to complex (switched menus and titlesets), you should
251
-be able to do what you want with 'tovid disc'.
252
-</P>
253
-
254
-<A NAME="toc9"></A>
255
-<H2>Usage</H2>
256
-
257
-<PRE>
258
-   tovid disc [OPTIONS] \
259
-      -files &lt;file list&gt; -titles &lt;title list&gt;
260
-      -out mydvd
261
-</PRE>
262
-
263
-<P>
264
-For example:
265
-</P>
266
-
267
-<PRE>
268
-   $ tovid disc -files File1.mpg File2.mpg File3.mpg \
269
-        -titles "Episode 1" "Episode 2" "Episode 3" \
270
-        -out Season_one
271
-</PRE>
272
-
273
-<P>
274
-The number of <B>-files</B> and <B>-titles</B> must be equal, though if you do not
275
-include any titles <B>tovid disc</B> will use the basename of the included files
276
-as titles.  If you are doing a slideshow or multiple slideshows, use
277
-<B>-slides</B> rather than <B>-files</B> for passing in the images.  You may use
278
--files and -slides more than once to create an ordering in a mixed
279
-slideshows/videos menu.  See Slideshows part of Usage section, below.
280
-</P>
281
-<P>
282
-If the input files are not mpeg, you will have the option to auto-encode them.
283
-</P>
284
-<P>
285
-General Options
286
-</P>
287
-<P>
288
-<B>At present there are 2 display arrangements or "templates":</B>
289
-</P>
290
-
291
-<DL>
292
-<DT>A. (Default)</DT><DD>
293
-    Thumbs will be centred, and as large as space restraints allow.
294
-<P></P>
295
-<DT>B. <B>-showcase</B> IMAGE|VIDEO</DT><DD>
296
-    Produces an arrangement with small buttons on
297
-    the side and the showcase image/video in the centre.  If no IMAGE or VIDEO
298
-    argument is supplied, the central thumb will be omitted.
299
-<P></P>
300
-    Note: <B>-textmenu</B>, <B>-quick-menu</B> and <B>-switched-menus</B> are all types
301
-    of showcase style menus.  See descriptions under <B>Menu style</B> section.
302
-</DL>
303
-
304
-<P>
305
-The <B>-titles</B> arguments should be double or single quoted, or have the spaces
306
-backslash-escaped. Special characters (like ", !, *, &amp;, ?) may need to be
307
-backslash-escaped.  To include a quoted string within a title, backslash-escape
308
-the quotes.  These titles are used for labelling thumbnails on the main menu,
309
-and for the submenu title for that video.  ( see also <B>-submenu-titles</B> )
310
-</P>
311
-<P>
312
-The <B>-showcase</B> styles can use longer titles than the default arrangement.
313
-With a showcase style, use: <B>-showcase-titles-align west</B> to give more space
314
-for the title, or use <B>-showcase-titles-align east</B> to allow titles of more
315
-than one line.
316
-</P>
317
-<P>
318
-The default style can only show about 16 characters (depending on the number
319
-of thumbs, and what <B>-titles-font</B> and <B>-titles-fontsize</B> is being used).
320
-If your titles are too long to fit in the label area, you may try using
321
-sub-menus, which can display longer titles, for example:
322
-</P>
323
-
324
-<PRE>
325
-   $ tovid disc -submenus \
326
-        -files file1.mpg file2.mpg ... \
327
-        -titles "Short 1" "Short 2" \
328
-        -submenus \
329
-        -submenu-titles "Long Title One" "Long Title Two" \
330
-        -out foo
331
-  
332
-</PRE>
333
-
334
-<P>
335
-The <B>-align</B> argument will position both titles and thumbs either south,
336
-north east, west, southwest, northwest, southeast, northeast, subject to
337
-certain constraints of each arrangement. For example a showcase style with
338
-a showcase thumb can only do north|south|center.
339
-</P>
340
-<P>
341
-More Examples:
342
-</P>
343
-<P>
344
-A text-only menu:
345
-</P>
346
-
347
-<PRE>
348
-   $ tovid disc -textmenu ...
349
-</PRE>
350
-
351
-<P>
352
-No menu:
353
-</P>
354
-
355
-<PRE>
356
-   $ tovid -nomenu -files file1.mpg file2.mp4 "file 3.avi" -out mydvd
357
-</PRE>
358
-
359
-<P>
360
-<B>Titlesets</B>
361
-</P>
362
-<P>
363
-A word should be mentioned here about titlesets, which is really just a
364
-hierarchy of menus.  You need to use titlesets, for example, if you have videos
365
-of different resolutions, or otherwise want to arrange videos on separate menus.
366
-If you want to have titlesets you need to put all the options for each titleset
367
-menu you would like to have between <B>-titleset</B> and <B>-end-titleset</B> options.
368
-</P>
369
-<P>
370
-Additionally, for the main menu (the opening menu that will let you jump to
371
-each titleset), you need to put options between <B>-vmgm</B> and <B>-end-vmgm</B>.
372
-You do not use <B>-files</B> for the opening menu options (<B>-vmgm</B>), but you
373
-will need as many TITLES after <B>-titles</B> as you have menus.
374
-</P>
375
-<P>
376
-Any options outside the <B>-titleset</B> <B>-end-titleset</B> and <B>-vmgm</B>
377
-<B>-end-vmgm</B> areas will be global options applying to every titleset.
378
-If a global option is duplicated inside a <B>-titleset</B> or <B>-vmgm</B> area, the
379
-global option will be overridden.
380
-</P>
381
-<P>
382
-Note: you do not need titlesets for a single menu with chapter break menus, for
383
-that just use <B>-submenus</B> or <B>-ani-submenus</B>
384
-</P>
385
-<P>
386
-Example of using <B>tovid disc</B> with titlesets:
387
-</P>
388
-
389
-<PRE>
390
-   $ tovid disc -static -out MY_DVD \
391
-     \
392
-     -titleset \
393
-     -files 1.mpg 2.mpg 3.mpg \
394
-     -titles "Title One" "Title Two" "Title Three" \
395
-     -end-titleset \
396
-     \
397
-     -titleset \
398
-     -files 4.mpg 5.mpg \
399
-     -titles "Title Four" "Title Five" \
400
-     -background foo.jpg \
401
-     -showcase bar.png \
402
-     -end-titleset \
403
-     \
404
-     -vmgm \
405
-     -titles "Season One" "Season Two" \
406
-     -background bg.jpg \
407
-     -bgaudio foo.mp3 \
408
-     -titles-fontsize 20 \
409
-     -end-vmgm
410
-</PRE>
411
-
412
-<P>
413
-See also <B>-titleset</B> and <B>-vmgm</B>
414
-</P>
415
-<P>
416
-<B>Slideshows</B>
417
-</P>
418
-<P>
419
-You can also use <B>tovid disc</B> to make slideshows.  This can either be a single
420
-slideshow, or multiple slideshows on the same menu.
421
-Remember to use <B>-slides</B> rather than <B>-files</B> for passing in the
422
-images.  Images can be any filetype that imagemagick supports: for example
423
-JPEG, PNG, GIF, TGA BMP etc.  For a single slideshow do not use <B>-titles</B>:
424
-use -menu-title to set the slideshow title.
425
-</P>
426
-<P>
427
-For a single slideshow the default is an animated menu that transitions from
428
-slide to slide.  The default transition type is 'crossfade', which fades each
429
-slide into the next and loops back to the first slide at the end.  If instead
430
-you use <B>-static</B>, then a static 'polaroid stack' menu of all the slides is
431
-created, with a single spumux'ed button for navigating with the enter key.  You
432
-may have to experiment to find out which DVD remote button advances the slides.
433
-Try the 'next chapter'(skip ?) button and the play or enter buttons.
434
-If you want to limit the number of slides in the menu to a subset of all files
435
-entered with <B>-slides</B>, then use <B>-menu-slide-total</B> INT.  Be sure to use
436
-a long enough audio file for <B>-bgaudio</B> or set <B>-menu-length</B> so the menu
437
-is long enough to support the slides plus transitions.
438
-</P>
439
-<P>
440
-You can also put multiple slideshows on one menu.  To do this, use
441
-<B>-slides IMAGES</B> for each slideshow desired.  You can even mix videos
442
-with slideshows by using <B>-files</B> <B>-slides</B> <B>-titles</B> multiple times.
443
-</P>
444
-<P>
445
-Example of a single slideshow with an animated menu with transitions:
446
-</P>
447
-
448
-<PRE>
449
-   $ tovid disc -menu-title "Autumn in Toronto" -slides images/*.jpg \
450
-      -menu-slide-total 20 -slide-transition crossfade -bgaudio slideshow.wav \
451
-      -out myslideshow
452
-</PRE>
453
-
454
-<P>
455
-Example of multiple slideshows on one menu:
456
-</P>
457
-
458
-<PRE>
459
-   $ tovid disc -menu-title "Autumn in Toronto" \
460
-     -slides photos/september/*.jpg \
461
-     -slides photos/october/*.jpg \
462
-     -slides photos/november/*.jpg \
463
-     -tile3x1 -rotate -5 5 -5 -align center \
464
-     -bgaudio background.wav \
465
-     -out myslideshow
466
-</PRE>
467
-
468
-<P>
469
-Example of mixed videos and slideshows:
470
-</P>
471
-
472
-<PRE>
473
-   $ tovid disc -menu-title "Autumn in Toronto" \
474
-     -files fall_fair.mov \
475
-     -slides  photos/september/*.jpg \
476
-     -files harvest.mpg \
477
-     -slides photos/october/*.jpg \
478
-     -titles "Fall Fair" "September" "Harvest" "October" \
479
-     -background autumn.png \
480
-     -bgaudio bg.mp3 \
481
-     -out myslideshow
482
-</PRE>
483
-
484
-<P>
485
-See the other slideshow options in the Slideshows options section.
486
-</P>
487
-<P>
488
-<B>Encoding Options</B>
489
-</P>
490
-<P>
491
-These are options for reencoding your non-compliant videos.  They are passed
492
-directly to the <B>tovid mpg</B> command which is invoked by <B>tovid disc</B> when
493
-non-compliant files are found.  For details, see the <B>Command:mpg</B> section.
494
-Here is a list of possible options you can pass:
495
-    <B>-config</B>, <B>-ntscfilm</B>, <B>-dvd-vcd</B>, <B>-half-dvd</B>, <B>-kvcd</B>,
496
-    <B>-kvcdx3</B>, <B>-kvcdx3a</B>, <B>-kdvd</B>, <B>-bdvd</B>, <B>-704</B>, <B>-normalize</B>,
497
-    <B>-amplitude</B>, <B>-overwrite</B>, <B>-panavision</B>, <B>-force</B>, <B>-fps</B>,
498
-    <B>-vbitrate</B>, <B>-quality</B>, <B>-safe</B>, <B>-crop</B>, <B>-filters</B>,
499
-    <B>-abitrate</B>, <B>-priority</B>, <B>-deinterlace</B>, <B>-progressive</B>,
500
-    <B>-interlaced</B>, <B>-interlaced_bf</B>, <B>-type</B>, <B>-fit</B>, <B>-discsize</B>,
501
-    <B>-parallel</B>, <B>-mkvsub</B>, <B>-autosubs</B>, <B>-subtitles</B>, <B>-update</B>,
502
-    <B>-mplayeropts</B>, <B>-audiotrack</B>, <B>-downmix</B>, <B>-ffmpeg</B>, <B>-nofifo</B>,
503
-    <B>-from-gui</B>, <B>-slice</B>, <B>-quiet</B>,
504
-    <B>-fake</B>, <B>-keepfiles</B>
505
-</P>
506
-
507
-<A NAME="toc10"></A>
508
-<H2>General Options</H2>
509
-
510
-<DL>
511
-<DT><B>-keep-files</B>, <B>-keepfiles</B></DT><DD>
512
-    Keep all intermediate/temporary files (helps with debugging)
513
-<DT><B>-no-ask</B> | <B>-noask</B></DT><DD>
514
-    Skip all interactive questions.  No preview, automatic re-encoding with
515
-    tovid if needed, no interactive option to use background video for bgaudio.
516
-<DT><B>-no-warn</B>, <B>-nowarn</B></DT><DD>
517
-    Don't pause after outputting warning or info messages
518
-<DT><B>-jobs</B></DT><DD>
519
-    By default, <B>tovid disc</B> starts a parallel job for each processor
520
-    detected.  With this option you can manually set the number of jobs.  For
521
-    example if you have a computer with 2 CPUs you can set "-jobs 1" to keep
522
-    one processor free for other things.  At present this applies to the time
523
-    consuming imagemagick loops: you will notice a substantial speedup now if
524
-    you have a multi-cpu system.
525
-<DT><B>-grid</B></DT><DD>
526
-    Show a second preview image with a grid and numbers that will help in finding
527
-    coordinates for options that might use them, like <B>-text-start</B>
528
-<DT><B>-no-confirm-backup</B></DT><DD>
529
-    This option is for when your DVD contains images for a slideshow.
530
-    Slideshows are an experimental (but well tested) feature.  Todisc is
531
-    unlikely to overwrite your personal files, but you should take precautions
532
-    and backup your images, as you would with any beta software.  Todisc
533
-    will prompt you to backup your files normally.  If you have already backed
534
-    up your images, use this option to disable the prompt.
535
-<P></P>
536
-==Options==
537
-<P></P>
538
-<DT><B>-ntsc</B></DT><DD>
539
-    720x480 output, compatible with NTSC standard (default)
540
-<DT><B>-pal</B></DT><DD>
541
-    720x576 output, compatible with PAL standard
542
-<DT><B>-submenus</B></DT><DD>
543
-    Create a sub-menu with chapters for each video (default: no sub-menus)
544
-<DT><B>-ani-submenus</B></DT><DD>
545
-    Create an animated sub-menu with chapters for each video (default: not
546
-    animated)
547
-<DT><B>-no-menu | -nomenu</B></DT><DD>
548
-    With this option todisc will just create a DVD file system, ready for
549
-    burning, with NO MENU, just the supplied video files.  These do not need
550
-    to be compliant, as non-compliant files will be encoded as usual.  The
551
-    <B>-out</B> option is not required.  Each  video will be a chapter unless
552
-    <B>-chapters</B> OPTION is passed.  The  <B>-chapters</B> option is a number
553
-    indicating the chapter interval in minutes, or a HH:MM:SS string
554
-    indicating chapter points.  See <B>-chapters</B>
555
-<DT><B>-encode-only</B></DT><DD>
556
-    This option was originally meant for the GUI, to allow it to be used for
557
-    just encoding rather than making a DVD structure.  But it works well from
558
-    the command line as well as it has the added advantage that you can input
559
-    a list of files.  Remember any makempg ('tovid mpg') options you use will
560
-    be passed on to the makempg script when encoding.
561
-</DL>
562
-
563
-<A NAME="toc11"></A>
564
-<H2>Menu style</H2>
565
-
566
-<DL>
567
-<DT><B>-showcase</B> IMAGE|VIDEO</DT><DD>
568
-    If used without an argument, use showcase style without a central thumb.
569
-    This is a different arrangement of images for the menu: small thumbnails
570
-    go at left (and right) side of screen, with a larger image in the centre.
571
-    Maximum of 10 videos.  If the provided argument is a video file, the
572
-    central thumb will be animated (regardless of whether <B>-static</B> is part
573
-    of the command line). Only 4:3 or 16:9 videos and images are accepted for
574
-    for the showcase file: if not one of these todisc will assume it is the
575
-    aspect ratio as the videos in the titleset.
576
-<DT><B>-textmenu</B>, <B>-text-menu</B> NUM</DT><DD>
577
-    If used without an argument, create a textmenu out of the supplied titles
578
-    The optional argument specifies how many titles are in the 1st column,
579
-    i.e. giving 4 titles and using "-textmenu 2" would make 2 columns of 2
580
-    titles. The default is to put all titles up to 13 in the first column
581
-    before starting a second column.  Maximum: 2 columns and 26 titles.
582
-    Note that column 2 titles are justified to the left unless you add
583
-    <B>-edge-justify</B> to the command line. The menu will be static if no video
584
-    files are supplied with either <B>-background</B> or <B>-showcase</B> options.
585
-<DT><B>-quick-menu</B></DT><DD>
586
-    If you are using ffmpeg 0.8 or newer you can use this option.  This will
587
-    make a very quick  menu by using ffmpeg instead of imagemagick.
588
-    There are two choices: you can either use '-showcase IMAGE|VIDEO' or
589
-    '-background VIDEO'.  There are no fancy effects like <B>-wave</B>
590
-    or <B>-rotate</B> available for it, but it is extremely fast.  It will be a
591
-    text-menu style of menu, with no video thumbs, and a central showcase
592
-    IMAGE(static) | VIDEO(animated).
593
-    (i) see <B>-bg-color</B> if you are not using a <B>-background</B> and want to
594
-    change the default.  (default is dark blue for -quick-menu arrangements). )
595
-    (ii) Note: todisc will still work with 'vhooks' if you have an old ffmpeg
596
-    with vhooks compiled in.
597
-<P></P>
598
-    Specifying the IMAGE|VIDEO argument to <B>-showcase</B> is mandatory for this
599
-    style of menu, unless used in conjunction with <B>-switched-menus</B>
600
-    in which case the videos passed with <B>-files</B> automatically become the
601
-    showcase videos.  If <B>-quick-menu</B> is used in combination with
602
-    <B>-switched-menus</B> it really speeds up an otherwise time consuming process.
603
-<P></P>
604
-    Example:
605
-<PRE>
606
-      -quick-menu -showcase /home/grepper/showcase.mpg
607
-</PRE>
608
-
609
-    See <B>-switched-menus</B> for example of making switched menus with
610
-    <B>-quick-menu</B>
611
-<P></P>
612
-<DT><B>-bg-color</B>, <B>-bg-colour</B></DT><DD>
613
-    The color to use for the menu background. (default: ntsc-safe black)
614
-    Note: use a color a great deal darker than you want, as it appears quite
615
-    a bit lighter in the video version.  You can use hexadecimal ('#ffac5f')
616
-    notation or named colors ('Lime').  convert -list color will show them.
617
-    See <A HREF="http://www.imagemagick.org/script/color.php">colors</A> for more details.
618
-<DT><B>-submenu-bg-color</B>, <B>-submenu-bg-colour</B></DT><DD>
619
-    The color to use as background for the  submenu(s).
620
-    (default: ntsc-safe black)  See <B>-bg-color</B>
621
-<DT><B>-static</B></DT><DD>
622
-    Main menu will consist of static thumbnail links. (default: animated)
623
-    If you use a video for -showcase or -background then it will still be
624
-    a 'moving' menu, in spite of the static buttons.  This option also does
625
-    double duty for the <B>-switched-menus</B> option, and will create static
626
-    "switched" images.
627
-    See also <B>-switched-menus</B>
628
-<DT><B>-background</B> IMAGE|VIDEO</DT><DD>
629
-    Menu background.  This can be a image file or an video file.  If it is a
630
-    video file the background will be animated.  Pick a file of correct aspect
631
-    ratio: i.e. it should still look good when resized to 4:3 aspect ratio.
632
-    It will be resized to fill the entire background.
633
-<DT><B>-submenu-background</B> IMAGE</DT><DD>
634
-    Submenu background.  This can be only be an image file.  Pick a file of
635
-    correct aspect ratio: i.e. it should still look good when resized to
636
-    4:3 aspect ratio.  It will be resized to fill the entire background.
637
-<DT><B>-menu-title</B></DT><DD>
638
-    Title for the root menu - may be longer than thumbnail labels
639
-    Also if you use \n in the title, you can use multi line titles, but you
640
-    would need to adjust <B>-title-fontsize</B> to something smaller than default
641
-    for example:
642
-<P></P>
643
-<PRE>
644
-      $ tovid disc ... -menu-title "A\nMultilined\nTitle" -title-fontsize 24
645
-</PRE>
646
-
647
-<DT><B>-title-font</B>, <B>-menu-font</B> FONT</DT><DD>
648
-    Font to use for titles, either by ImageMagick font name (ex., "Arial") or
649
-    explicit pathname (ex., "/full/path/to/arial.ttf"). To see a complete
650
-    list of acceptable ImageMagick font names, run <B>convert -list type</B>, and
651
-    refer to the leftmost column
652
-<DT><B>-title-fontsize</B>, <B>-menu-fontsize</B></DT><DD>
653
-    Font size for main menu - best to -preview if you use this
654
-<DT><B>-submenu-font</B></DT><DD>
655
-    Font to use for the sub-menu main titles.  See <B>-title-font</B>
656
-<DT><B>-submenu-fontsize</B></DT><DD>
657
-    Font size for the sub-menu main titles
658
-<DT><B>-menu-fade</B> ['BACKGROUND DURATION']</DT><DD>
659
-    Fade the menu in and out The background will fade in first, then title (and
660
-    mist if called for), then the menu thumbs.  The fadeout is in reverse
661
-    order.  'BACKGROUND DURATION' is an integer denoting the amount of time
662
-    the background will play before the menu begins to fade in.  This can allow
663
-    you to do a 'transition' to the menu: if you supply a -background VIDEO it
664
-    will play for the indicated time before the menu fades in.  Leave the
665
-    optional argument empty (just <B>-menu-fade</B>) to get the default behavior
666
-    of showing the background for 1 second before fading the menu in.  To
667
-    disable the fadeout portion, use '<B>-loop</B> inf'.  See also:
668
-    <B>-transition-to-menu</B> and <B>-loop</B>
669
-<DT><B>-transition-to-menu</B></DT><DD>
670
-    This option goes with the <B>-menu-fade</B> option above, which must be
671
-    enabled for it to have effect.  It is a convenience option for animated
672
-    backgrounds: the background will become static at the exact point the
673
-    thumbs finish fading in. This menu does not loop unless you pass
674
-    <B>-loop</B> VALUE.  See also: <B>-loop</B>
675
-<DT><B>-bgaudio</B>, <B>-bg-audio*</B> FILE</DT><DD>
676
-    An file containing audio for the main menu background.  For static menus
677
-    the default is to use 20 seconds of audio.  You can change this using the
678
-    <B>-menu-length</B> option.
679
-<DT><B>-submenu-audio</B> FILE(S)</DT><DD>
680
-    List of files for sub-menu audio backgrounds. If one file is given, then
681
-    it will be used for all sub-menus.  Otherwise the number given must equal
682
-    the number of submenus, though the keyword "none" in this list may be used for
683
-    silence.  See also <B>-submenu-length</B>
684
-<DT><B>-titleset</B> . . . <B>-end-titleset</B></DT><DD>
685
-    If you have more than one titleset, put options for each titleset between
686
-    <B>-titleset</B> and <B>-end-titleset</B>.  A separate menu will be created that
687
-    can be accessed from the main menu (VMGM).  You can create this main menu
688
-    using the <B>-vmgm</B> <B>-end-vmgm</B> options.  See <B>-vmgm</B> below and
689
-    TITLESET paragraph opening <B>Usage</B> section.
690
-<DT><B>-vmgm</B> . . . <B>-end-vmgm</B></DT><DD>
691
-    The VMGM menu is the root menu when you use titlesets.
692
-    Put your VMGM menu options between <B>-vmgm</B> and <B>-end-vmgm</B>.
693
-    You only need <B>-titles</B> "Titleset One title"  "Titleset Two title"
694
-    . . . , and not <B>-files</B>.
695
-    Any other options can be used, but the  menu will be a textmenu style by
696
-    default.  <B>Hint</B>: use <B>-showcase</B> IMAGE/VIDEO to create a fancier
697
-    VMGM menu.
698
-<DT><B>-no-vmgm-menu</B>, <B>-no-vmgm</B></DT><DD>
699
-  This will skip the creation of a VMGM ( root menu ) for titlesets. The DVD
700
-  will start with the first titleset.  You can not use this option unless also
701
-  using <B>-quick-nav</B> as you would not have a way to get to other titlesets.
702
-<DT><B>-skip-vmgm</B></DT><DD>
703
-  Start DVD from the first titleset instead of the VMGM ( root ) menu.
704
-<DT><B>-switched-menus</B>, <B>-switched-menu</B></DT><DD>
705
-    This will make a "switched menu": there will be a central image where the
706
-    showcase image would go, and text menu titles along the menu edge where
707
-    textmenu titles go.  As you select a video title with the down or up arrow
708
-    on your DVD remote, the image in the centre will change to the image or
709
-    video made from that selected video. Do not use <B>-showcase</B> IMAGE/VIDEO
710
-    with this option.
711
-<P></P>
712
-    This can be a time consuming process for making animated menus as you need
713
-    to make a separate menu for each video provided with <B>-files</B>.  The
714
-    process can be greatly sped up by using <B>-quick-menu</B> in conjunction with
715
-    this, though you will lose fancy options like <B>-rotate</B> and <B>-wave</B>.
716
-<P></P>
717
-    Note that if you want to just have a static rather than an 'animated'
718
-    image, add <B>-static</B> to the command line.
719
-<P></P>
720
-    Example for using with <B>-quick-menu</B>:
721
-<PRE>
722
-      -switched-menus -quick-menu
723
-</PRE>
724
-
725
-</DL>
726
-
727
-<A NAME="toc12"></A>
728
-<H2>Thumbnail style</H2>
729
-
730
-<DL>
731
-<DT><B>-titles-font</B> FONT</DT><DD>
732
-    Display thumbnail or textmenu titles in the given font
733
-<DT><B>-titles-fontsize</B> POINTS</DT><DD>
734
-    Font size to use for thumbnail or textmenu titles
735
-<DT><B>-thumb-shape</B></DT><DD>
736
-    normal|oval|vignette|plectrum|arch|spiral|blob|star|flare
737
-    Apply a shaped transparency mask to thumbnail videos.
738
-    These "feathered" shapes look best against a plain background (or used
739
-    in conjunction with <B>-thumb-mist</B> [COLOR]).  For this rectangular
740
-    semi-transparent misted background for each thumb:  see <B>-thumb-mist</B>.
741
-    Note: if you wish to make your own mask PNGS you can put them in
742
-    $PREFIX/lib/tovid/masks/ or $HOME/.tovid/masks/ and use them on the
743
-    command line using the filename minus the path and extension.
744
-    (i.e ~/.tovid/masks/tux.png becomes -thumb-shape tux)
745
-    No frame is used for shaped thumbs.
746
-<DT><B>-thumb-frame-size</B> INT</DT><DD>
747
-    The size (thickness) of the thumb frames in pixels.  This will also set the
748
-    thickness of the raised "frame" of thumbs when you use <B>-3d-thumbs</B>.
749
-    See also <B>-showcase-frame-size</B> and <B>-thumb-frame-color</B>
750
-<DT><B>-thumb-frame-color</B>, <B>-thumb-frame-colour</B> COLOR</DT><DD>
751
-    The color of frames for video thumbnails.  Use hexadecimal or named colors
752
-    notation.  Remember to quote if using hexadecimal! ( '#ffac5f' ).
753
-<DT><B>-3d-thumbs</B>, <B>-3dthumbs</B></DT><DD>
754
-    This will give an illusion of 3D to the thumbnails: dynamic lighting on
755
-    rounded thumbs, and a raised effect on rectangular thumbs.  Try it !
756
-</DL>
757
-
758
-<A NAME="toc13"></A>
759
-<H2>Slideshows</H2>
760
-
761
-<DL>
762
-<DT><B>-slides</B> IMAGES</DT><DD>
763
-    Use <B>-slides</B> IMAGES to pass in images for a slideshow.  The default is
764
-    to make an animated menu of the slides, moving from one slide to the
765
-    next. If you use <B>-static</B>, a 'polaroid stack' montage is created.  This
766
-    composites the slides onto the background in 'random' locations with random
767
-    rotations.  <B>-slides</B>  IMAGES can be used multiple times if you wish to
768
-    make a menu with multiple slideshows.  You can also make a menu
769
-    of mixed videos and slideshows by using <B>-slides</B> IMAGES, and <B>-files</B>
770
-    VIDEOS multiple times.  For such a menu, the number of <B>-titles</B>
771
-    needs to match the number of <B>-files</B> passed in plus the number of
772
-    slideshows.  (Each time you use <B>-slides</B> counts as one title.)  To use
773
-    a transition between the slides, use <B>-slide-transition</B>
774
-    crossfade|fade.  See <B>-slide-transition</B> <B>-menu-slide-total</B>
775
-<P></P>
776
-<DT><B>-menu-slide-total</B> INT</DT><DD>
777
-    Use INT number of the slides that were passed in with <B>-slides</B>
778
-    to make the animated or static slide menu.  The length of the menu is
779
-    determined by 1) <B>-menu-length</B> NUM if given,  and by 2) the length
780
-    of the audio from <B>-bgaudio</B>.  For submenu slideshows, it is determined
781
-    by 1) <B>-submenu-length</B> NUM if given,  and by 2) the length of the
782
-    audio from <B>-submenu-audio</B> FILE(S).
783
-<P></P>
784
-<DT><B>-submenu-slide-total</B> INT</DT><DD>
785
-    This option is the same as <B>-menu-slide-total</B> except that it is
786
-    for submenu slideshows.
787
-<P></P>
788
-<DT><B>-slide-transition</B> crossfade|fade [crossfade]</DT><DD>
789
-    The type of fade transition between slides in a animated slide menu.  Be
790
-    sure the menu length is long enough to support the 1 second transitions
791
-    between the slides.  The length is determined by 1) the length of the
792
-    -bgaudio AUDIO  2) the length given with -menu-length NUM.  For submenu
793
-    slideshows, it is determined by 1) <B>-submenu-length</B> NUM if given,  and
794
-    by 2) the length of the audio from <B>-submenu-audio</B> FILE(S).
795
-<P></P>
796
-    See <B>-menu-slide-total</B> , <B>-bgaudio</B> , <B>-menu-length</B> ,
797
-    <B>-submenu-length</B>, and <B>-submenu-audio</B>.
798
-<P></P>
799
-    The 'crossfade' transition fades from one slide to another.  The 'fade'
800
-    transition fades in and out from and to black.  If you don't use this
801
-    option, the default is to use a 'crossfade' transition.
802
-<P></P>
803
-<DT><B>-slideshow-menu-thumbs</B> FILES</DT><DD>
804
-    Use the FILES instead of the 1st image in each slideshow as the
805
-    thumb that shows on the menu.  This option is for multiple slideshows
806
-    or mixed slideshow/video menus only.
807
-<P></P>
808
-<DT><B>-slides-to-bin</B> FILES</DT><DD>
809
-    FILES will be resized to 640x480 using a 'box' filter - this
810
-    is called 'binning'.  It will reduce the 'signal to noise' ratio for the
811
-    image in the animated slide menu.  Use this if you get some unwanted
812
-    effects for certain images, such as pixels shifting in what should be a
813
-    static image.  See also <B>-slides-to-blur</B> and <B>-slide-border</B>
814
-<P></P>
815
-<DT><B>-slides-to-blur</B> FILES</DT><DD>
816
-    FILES will be blurred a small amount - which will help on
817
-    slides that still have noise even after 'binning' with -slides-to-bin.
818
-    The default blur is 0x0.2 - you can increase this with
819
-    -slide-blur ARG.  See also <B>-slides-to-bin</B> and <B>-slide-border</B>
820
-<P></P>
821
-<DT><B>-slide-blur</B> VALUE or LIST of VALUES [0x0.2]</DT><DD>
822
-    The argument to use for blurring files.  It will be passed to
823
-    imagemagick: convert -blur ARG.  The format of the arg is {radius}x{sigma}
824
-    and the default is 0x0.2. Using values between 0x0.1 and 0x0.9 is probably
825
-    the best range.  Use a single value for all, or a list to have a different
826
-    blur for each file passed with <B>-slides-to-blur</B>.  You must pass in
827
-    <B>-files-to-blur</B> FILES to use this option.  Blurring can help 'noise'
828
-    problems in the video.  See also <B>-slides-to-bin</B> and <B>-slide-border</B>
829
-<P></P>
830
-<DT><B>-slide-border</B> WIDTH [100]</DT><DD>
831
-    Pad the slides with a border for the animated slide menu.  The default
832
-    without using an argument is 100.  Using this option can also solve some
833
-    noise/ringing effects if used alone or in conjunction with 'binning'
834
-    (<B>-slides-to-bin</B>) or blurring (<B>-slides-to-blur</B>).
835
-<P></P>
836
-<DT><B>-slide-frame</B> WIDTH [12]</DT><DD>
837
-    Frame the slides for the animated slideshow menu.  The default width
838
-    without using an  argument is 12.  See also <B>-slide-frame-color</B>
839
-<P></P>
840
-<DT><B>-slide-frame-color</B>, <B>-slide-frame-colour</B></DT><DD>
841
-    The color of the slide frame if passing <B>-slide-frame</B>.  The default if
842
-    you don't use this option is a color-safe white: rgb(235,235,235).
843
-<P></P>
844
-<DT><B>-showcase-slideshow</B></DT><DD>
845
-    If doing multiple slideshows or mixed videos and slideshow(s), then use
846
-    the animated slideshow as a showcase video.  It will be composed of slides
847
-    from each slideshow in the menu.  The thumb for each slideshow button will
848
-    be static.  If you used with a mixed menu of videos and slideshows, then
849
-    the video thumbs WILL be animated, so you may wish to use -static or
850
-    -textmenu with the option in that case.  If you want to use the
851
-    **-switched-menus option with a mixed menu leave this option out.
852
-<P></P>
853
-<DT><B>-background-slideshow</B>, <B>-bg-slideshow</B></DT><DD>
854
-    If doing multiple slideshows or mixed videos and slideshow(s), then use
855
-    the animated slideshow as a background video.  See <B>-showcase-slideshow</B>
856
-    for additional details.
857
-<P></P>
858
-<DT><B>-no-confirm-backup</B></DT><DD>
859
-    Slideshows are an experimental (but well tested) feature.  Todisc is
860
-    unlikely to overwrite your personal files, but you should take precautions
861
-    and backup your images, as you would with any beta software.  Todisc
862
-    will prompt you to backup your files normally.  If you have already backed
863
-    up your images, use this option to disable the prompt.
864
-    See <B>General Options</B>
865
-<P></P>
866
-<DT><B>-use-dvd-slideshow</B> <A HREF="FILE">CONFIG</A></DT><DD>
867
-    If you pass this option without an argument, tovid will use the
868
-    dvd-slideshow program to create the animated slide menu, assuming you have
869
-    this program installed.  The optional argument is the dvd-slideshow
870
-    configuration file  - if you don't use this argument tovid will create it
871
-    for you.  If you want to use the 'Ken Burns effect' - then the
872
-    configuration file argument is required.  Note: the configuration file will
873
-    override many of the above options for slideshows.
874
-</DL>
875
-
876
-<A NAME="toc14"></A>
877
-<H2>Burning the disc</H2>
878
-
879
-<DL>
880
-<DT><B>-burn</B></DT><DD>
881
-    Prompt to burn the DVD directory on completion.
882
-<P></P>
883
-<DT><B>-device</B></DT><DD>
884
-    Device to use for the burning program [ /dev/dvdrw ]
885
-<P></P>
886
-<DT><B>-speed</B></DT><DD>
887
-    The speed to use for burning the disc.
888
-</DL>
889
-
890
-<A NAME="toc15"></A>
891
-<H2>Advanced usage</H2>
892
-
893
-<H3>Options</H3>
894
-
895
-<DL>
896
-<DT><B>-menu-length</B></DT><DD>
897
-    The desired animated main menu length in seconds
898
-<DT><B>-submenu-length</B></DT><DD>
899
-    The desired submenu length.  This will also affect the length of submenu
900
-    audio for static submenus.  (Assuming that -submenu-audio was passed in).
901
-    The default is to use 10 seconds of audio for static menus.
902
-<DT><B>-submenu-stroke</B> COLOR</DT><DD>
903
-    The color for the sub-menu font shadow
904
-<DT><B>-submenu-title-color</B>, <B>-submenu-title-colour</B></DT><DD>
905
-    The fill color used for sub-menu title fonts
906
-<DT><B>-submenu-titles</B></DT><DD>
907
-    You can supply a list of titles here for sub-menus without the length
908
-    restrictions found in thumb titles.  Must equal number of videos
909
-<DT><B>-chapters</B> [ NUM | CHAPTER POINTS in HH:MM:SS ]</DT><DD>
910
-    The number of chapters for each video (default: 6) OR
911
-    the actual chapter points in HH:MM:SS format.
912
-    Chapter points will be used for generating the submenu thumbs, and for
913
-    seeking with your DVD player.  You can pass in just one value that will
914
-    be used for all videos, or supply a list of values (number of chapters)
915
-    or time code strings.
916
-<P></P>
917
-    If you just pass an integer for 'number of chapters', then tovid will
918
-    make the chapter points for you by dividing the video length by the number
919
-    you supply.  If using the <B>-no-menu</B> option, the INT passed in will be
920
-    the chapter interval in minutes, rather than the above formula.
921
-<P></P>
922
-    If passing HH:MM:SS format you need to pass the string of chapter points for
923
-    each video and each string should have comma separated values.
924
-    Additionally, the first chapter should always start at 00:00:00 as
925
-    dvdauthor will add that if it is not there already.
926
-<P></P>
927
-    To get your time codes, you can play your videos in mplayer and press 'o'
928
-    to see them on-screen.  I have found these to be very accurate in my short
929
-    tests.  For greater frame accuracy you could try loading the file in
930
-    avidemux and find the time codes for the frames you want.
931
-<P></P>
932
-    If passing grouped chapters you need to join the chapters from all the
933
-    videos in a group with a '+' separator.  If you want to skip creating
934
-    chapters for a video in the group use '0' for its chapters.
935
-<P></P>
936
-    Note: chapters for grouped videos should probably be passed in using the
937
-    above HH:MM:SS format. (Arbitrary chapters using just an INT for the # of
938
-    chapters is not guaranteed to work reliably in all cases for grouped videos
939
-    at the moment.)
940
-<P></P>
941
-    Example for passing just number of chapters ( 4 videos ):
942
-<PRE>
943
-      -chapters 5 2 4 8
944
-</PRE>
945
-
946
-<P></P>
947
-    Example of passing chapter points ( 4 videos ):
948
-<PRE>
949
-      -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45 \
950
-      00:00:00,00:04:25.623,00:09:12,00:15:51 \
951
-      00:00:00,00:05:10,00:13:41,00:18:13.033 \
952
-      00:00:00,00:15:23.342,00:26:42.523
953
-</PRE>
954
-
955
-<P></P>
956
-    Example of passing grouped chapters using the '+' separator:
957
-<PRE>
958
-      -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45+00:04:23,00:09:35 \
959
-      00:00:00... etc.
960
-</PRE>
961
-
962
-<P></P>
963
-<DT><B>-chapter-titles</B> LIST</DT><DD>
964
-    If you are using submenus, you can pass a list of titles for the
965
-    chapters.  Each title must be quoted, and the number of titles given
966
-    must equal the total number of chapters for all videos.  In other words
967
-    if you use -chapters 4 6 8 , you must give 18 chapter titles, in the same
968
-    order that the videos were passed in.  Note: if you are passing in options
969
-    on the command line to the 'tovid disc' GUI, you must repeat the option
970
-    <B>-chapter-titles</B> for each video, accompanied by its respective chapter
971
-    titles. (you can also choose to use this syntax for the todisc script.)
972
-<P></P>
973
-<DT><B>-chapter-font</B> FONT</DT><DD>
974
-    Use FONT as the font for submenu chapters.
975
-<P></P>
976
-<DT><B>-chapter-fontsize</B> SIZE</DT><DD>
977
-    Use SIZE as the pointsize for the chapters font.
978
-<DT><B>-chapter-color</B> COLOR</DT><DD>
979
-    The color for the chapters font.
980
-<DT><B>-chapter-stroke</B> COLOR</DT><DD>
981
-    The color for the chapters font shadow
982
-<P></P>
983
-<DT><B>-seek</B> NUM | "NUM1 NUM2 NUM3 . . ."</DT><DD>
984
-    Seek to NUM seconds before generating thumbnails (default: 2.0 seconds)
985
-    If a quoted string of values matching the number of videos is used, then
986
-    each video can use a different seek value
987
-    If using switched menus, the <B>-seek</B> value(s) will be used to generate
988
-    the showcase image that displays on switching to another video choice with
989
-    the up/down arrow keys.
990
-<DT><B>-fast-seek</B></DT><DD>
991
-    Use faster seek method for ffmpeg.  This is not as accurate as the default
992
-    method, and may produce grey frames.
993
-<DT><B>-frame-safe</B>  Instead of seeking and then outputting one frame for</DT><DD>
994
-    previews and static menus, output 9 frames and choose the largest.  Not
995
-    frame accurate (may be as much as 9 frames off), but safer.  Choose this
996
-    if you are getting grey frames/thumbnails with some videos.  You can also
997
-    use it to try to get the 'best' frame.  This option
998
-    has no effect on submenus at present.
999
-<DT><B>-showcase-seek</B> NUM</DT><DD>
1000
-    Seek to NUM seconds before generating thumbnails for showcase video
1001
-    (default: 2.0 seconds)
1002
-<DT><B>-bgvideo-seek</B>, <B>-bg-video-seek</B> NUM</DT><DD>
1003
-    Seek to NUM seconds before generating images for background video
1004
-    (default: 2.0 seconds)
1005
-<DT><B>-bgaudio-seek</B>, **-bg-audio-seek NUM</DT><DD>
1006
-    Seek to NUM seconds before generating audio for bgaudio
1007
-    (default: 2.0 seconds)
1008
-<DT><B>-group</B> N VIDEO1 VIDEO2 . . .</DT><DD>
1009
-    Allow grouping videos in dvdauthor.xml, so they will play sequentially as
1010
-    a group.  The videos passed in after the 'N' will be grouped with the 'Nth'
1011
-    video. Example:
1012
-<P></P>
1013
-<PRE>
1014
-      -group 2 2.mpg 3.mpg 4.mpg
1015
-</PRE>
1016
-
1017
-<P></P>
1018
-    will group these 3 videos with the 2nd video given with <B>-files</B>, so that
1019
-    they will play sequentially as one title.  Only one thumbnail and/or title
1020
-    will appear on the menu for the group: it will be made from the 1st video
1021
-    in the group.  In the above example if you passed:
1022
-<PRE>
1023
-      -files foo.mpg bar.mpg baz.mpg -group 2 2.mpg 3.mpg 4.mpg
1024
-</PRE>
1025
-
1026
-    then the group will consist of bar.mpg  2.mpg, 3.mpg and 4.mpg, and only the
1027
-    title and/or thumbnail for bar.mpg will appear in the menu.  You can use
1028
-    <B>-group</B> more than once for multiple groups.  Be  sure to quote video
1029
-    filenames if they contain  spaces.
1030
-</DL>
1031
-
1032
-<A NAME="toc16"></A>
1033
-<H2>Menu Style</H2>
1034
-
1035
-<DL>
1036
-<DT><B>-menu-title-geo</B> north|south|east|west|center [south]</DT><DD>
1037
-    The position of the menu title.  You may need to use -align as well if
1038
-    you don't want your title covering other parts of your menu.  See
1039
-    <B>-align</B>
1040
-<DT><B>-menu-title-offset</B> OFFSET (+X+Y)</DT><DD>
1041
-    Move menu title by this offset from its N|S|E|W|Center position.  You
1042
-    may need to use -align as well if you don't want your title covering other
1043
-    parts of your menu.  See <B>-align</B>
1044
-<DT><B>-button-style</B> line|rect|text|text-rect [line]</DT><DD>
1045
-    The style of button that you will see when you play the DVD.
1046
-    "line" style underlines the title, "rect" draws a rectangle around the
1047
-    thumb when you select it in the DVD player, "text" highlights the video
1048
-    title text, and "text-rect" draws a rectangle around the title
1049
-    text.
1050
-<DT><B>-title-color</B>, <B>-title-colour</B> COLOR</DT><DD>
1051
-    Color to use for the main menu title.  For list of supported colors do:
1052
-    <B>convert -list</B> color.  HTML notation may be used: "#ff0000". See:
1053
-    <A HREF="http://www.imagemagick.org/script/color.php">http://www.imagemagick.org/script/color.php</A>
1054
-<DT><B>-title-stroke</B> COLOR</DT><DD>
1055
-    Shadow color for the main menu's title font. Use "none" for transparent
1056
-    outline  (see title-color).  Note: this is not a -stroke in the sense that
1057
-    imagemagick uses the term, but a shadow (the font is drawn twice).  To get
1058
-    a true imagemagick stroke see <B>-title-font-deco</B>
1059
-<DT><B>-title-font-deco</B>, <B>-title-fontdeco</B> "IMAGEMAGICK STRING"</DT><DD>
1060
-    Sets the font decoration method to FONTDECORATION. It is used by the 'convert'
1061
-    ImageMagick command to draw the menu text. You can add colored text
1062
-    outlines, gradient fills, and many others. See <B>Usage notes</B>
1063
-<DT><B>-titles-stroke</B> COLOR</DT><DD>
1064
-    Shadow color for the thumb or textmenu video titles font. Use "none" for
1065
-    transparent outline  (see <B>-titles-color</B>).  Note: this is not a -stroke
1066
-    in the sense that imagemagick uses the term, but a shadow
1067
-    (the font is drawn twice).  To get a true imagemagick stroke,
1068
-    see <B>-titles-font-deco</B>
1069
-<DT><B>-titles-font-deco</B>, <B>-titles-fontdeco</B> "IMAGEMAGICK STRING"</DT><DD>
1070
-    Sets the font decoration method to FONTDECORATION. It is used by the 'convert'
1071
-    ImageMagick command to draw the menu text. You can add colored text
1072
-    outlines, gradient fills, and others. See <B>Usage notes</B> for more info.
1073
-<DT><B>-highlight-color</B>, <B>-highlight-colour</B></DT><DD>
1074
-    Color to use for the menu buttons that your DVD remote uses to navigate.
1075
-<DT><B>-select-color</B>, <B>-select-colour</B></DT><DD>
1076
-    Color to use for the menu buttons that your DVD remote uses to select.
1077
-<DT><B>-text-mist</B></DT><DD>
1078
-    Put a semi-transparent misted background behind the text for the menu's
1079
-    title, just slightly larger than the text area.
1080
-<DT><B>-text-mist-color</B>, <B>-text-mist-colour</B> COLOR</DT><DD>
1081
-    Color of the mist behind the menu's title (see title-color).
1082
-<DT><B>-text-mist-opacity</B></DT><DD>
1083
-    Opacity of the mist behind the menu's title - see <B>-opacity</B>
1084
-<DT><B>-title-opacity</B></DT><DD>
1085
-    Opacity of the menu title text
1086
-<DT><B>-titles-opacity</B></DT><DD>
1087
-    Opacity of the text for video titles
1088
-<DT><B>-submenu-title-opacity</B></DT><DD>
1089
-    Opacity of the text for submenu menu titles
1090
-<DT><B>-chapter-title-opacity</B></DT><DD>
1091
-    Opacity of the text for submenu chapter titles
1092
-<DT><B>-menu-audio-fade</B></DT><DD>
1093
-    Number of sec to fade given menu audio in and out (default: 1.0 seconds)
1094
-    If you use <B>-menu-audio-fade</B> 0 then the audio will not be faded.
1095
-<DT><B>-submenu-audio-fade</B></DT><DD>
1096
-    Number of secs to fade sub-menu audio in and out (default: 1.0 seconds).
1097
-    See <B>-menu-audio-fade</B>
1098
-<DT><B>-intro</B> VIDEO</DT><DD>
1099
-    Use a introductory video that will play before the main menu.
1100
-    At present it must be a DVD compatible video at the correct resolution etc.
1101
-    Only 4:3 aspect is supported: 16:9 will give unexpected results.
1102
-</DL>
1103
-
1104
-<H3>Style options specific to showcase/textmenu arrangements</H3>
1105
-
1106
-<DL>
1107
-<DT><B>-text-start</B> N</DT><DD>
1108
-    This option is for <B>-textmenu</B> menus.  The titles will start at the Nth
1109
-    pixel from the top of the menu ( Y axis ).
1110
-<DT><B>-title-gap</B> N</DT><DD>
1111
-    This option is for <B>-textmenu</B> menus.  The gap is the space between
1112
-    titles vertically ( Y axis ).
1113
-<DT><B>-rotate</B> DEGREES</DT><DD>
1114
-    Rotate the showcase image|video clockwise by DEGREES.
1115
-    (default: if used without options, the rotate will be 5 degrees).  Note:
1116
-    this will not turn a portait image into a landscape image!
1117
-<DT><B>-showcase-geo</B> GEOMETRY</DT><DD>
1118
-    The position of the showcase image.  ( +X+Y  position )
1119
-    For example: <B>-showcase-geo</B> +300+200
1120
-<DT><B>-wave</B> default|GEOMETRY</DT><DD>
1121
-    Wave effect for showcase image|video.  Alters thumbs along a sine wave using
1122
-    GEOMETRY. (default: no wave)
1123
-    "default" will produce a wave arg of -20x556, which
1124
-    produces a gentle wave with a small amount of distortion.
1125
-    See: <A HREF="http://www.imagemagick.org/Usage/distorts/#wave">http://www.imagemagick.org/Usage/distorts/#wave</A> if you want
1126
-    to try other values.
1127
-<DT><B>-showcase-shape</B>  egg|oval|plectrum|arch|spiral|galaxy|flat-tube|normal</DT><DD>
1128
-    Apply a shaped transparency mask to showcase videos or images.
1129
-    Note: if you wish to make your own mask PNGS you can put them in
1130
-    $PREFIX/lib/tovid/masks/ or $HOME/.tovid/masks/ and use them on the
1131
-    command line using the filename minus the path and extension.
1132
-    No frame is used for shaped thumbs.
1133
-<DT><B>-showcase-framestyle</B>  none|glass</DT><DD>
1134
-    For -showcase-* style template only
1135
-    "none" will use the default frame method, using "convert -frame . . ."
1136
-    "glass" will use mplayer to make frames, which gives an interesting
1137
-    animated effect to the frames, and can be much faster ( especially if you
1138
-    don't use <B>-rotate</B> or <B>-wave</B> as thumbs will not need to be processed
1139
-    again after mplayer spits them out.  Note: you need to be using either
1140
-    <B>-showcase</B> IMAGE or <B>-showcase</B> VIDEO for this "frame style" to work.
1141
-<DT><B>-showcase-frame-size</B> PIXELS</DT><DD>
1142
-    The size of the showcase frame.  This value will be used for both width and
1143
-    height for the 'thickness' of the frame.  This will also set the thickness
1144
-    of the raised "frame" of the showcase thumb when you use <B>-3d-showcase</B>.
1145
-    See also <B>-thumb-frame-size</B> and <B>-showcase-frame-color</B>
1146
-<DT><B>-showcase-frame-color</B>, <B>-showcase-frame-colour</B> PIXELS</DT><DD>
1147
-    The color of the showcase frame.  Use hexadecimal or named colors notation.
1148
-    Remember to quote! ( '#ffac5f' ).
1149
-<DT><B>-3d-showcase</B>, <B>-3dshowcase</B></DT><DD>
1150
-    This will give an illusion of 3D to the showcase thumb: dynamic lighting on
1151
-    rounded thumbs, and a raised effect on rectangular thumbs.  Try it !
1152
-</DL>
1153
-
1154
-<A NAME="toc17"></A>
1155
-<H2>Thumbnail Style</H2>
1156
-
1157
-<DL>
1158
-<DT><B>-user-thumbs</B> IMAGE(S)</DT><DD>
1159
-    Supply your own images for menu buttons, rather than relying on todisc to
1160
-    generate them from the video.  They must be the same aspect ratio as the
1161
-    videos in the titleset (4:3 or 16:9), as todisc will resize them without
1162
-    checking and cropping.  There must be on image for each thumb that will be
1163
-    displayed on the menu (ie. one thumb for each video in a titleset).
1164
-<DT><B>-opacity</B> [0-100] (default 100)</DT><DD>
1165
-    Opacity of thumbnail videos as a percentage (no percent sign).
1166
-    Anything less than 100(%) is semi-transparent. Not recommended with dark
1167
-    backgrounds.
1168
-<DT><B>-thumb-blur</B>, <B>-blur</B> NUM</DT><DD>
1169
-    The amount of feather blur to apply to the thumb-shape.  The default is 1.0
1170
-    which will more or less keep the shape and produces transparency at the
1171
-    edges.  Choose float or integer values between 0.1 and 2.0. 3D thumbs are
1172
-    set to a tiny blur, so this option doesn't affect the <B>-3dthumbs</B> option.
1173
-<DT><B>-showcase-blur</B> NUM</DT><DD>
1174
-    The amount of 'feather' blur to apply to the showcase image/video.  Choose
1175
-    values between 0.1 and 2.0.  This option has no effect on <B>-3d-showcase</B>.
1176
-    See <B>-thumb-blur</B> for more info.
1177
-<DT><B>-align</B> DIRECTION</DT><DD>
1178
-    This will align  thumbs/titles in DIRECTION, which is a compass direction
1179
-    as used by imagemagick: ie. north|south|east|west|northeast|northwest etc.
1180
-    If <B>-align</B> south then menu title will align north, unless you manually
1181
-    set one or both of <B>-menu-title-geo</B> or <B>-menu-title-offset</B>.
1182
-    Only <B>-align</B> north|south|center has any effect on showcase with thumb,
1183
-    or with the default montage arrangement of central thumbs. The most
1184
-    apparent changes with be with textmenu, though with 2 column arrangements
1185
-    only the north* and south* changes will show an effect.
1186
-<P></P>
1187
-    Diagram:
1188
-<DT>   . northwest   north   northeast .</DT><DD>
1189
-<DT>   .                               .</DT><DD>
1190
-<DT>   . west        center       east .</DT><DD>
1191
-<DT>   .                               .</DT><DD>
1192
-<DT>   . southwest   south    souteast .</DT><DD>
1193
-<DT><B>-thumb-mist</B> [COLOR]</DT><DD>
1194
-    Use a mist behind thumbnails.  The optional argument is the color of the
1195
-    mist.  This option helps with contrast.  Be sure to set the font color
1196
-    to an appropriate color if using a colored mist, and/or use a bold font.
1197
-<DT><B>-titles-color</B>, <B>-titles-colour</B> COLOR</DT><DD>
1198
-    Color to use for the thumb or textmenu titles.  If your titles are not
1199
-    clear enough or look washed out, try using a <B>-titles-stroke</B> that
1200
-    is the same color as used with <B>-titles-color</B>  (see <B>-title-color</B>)
1201
-<DT><B>-showcase-titles-align</B> west|east (default: center [centre])</DT><DD>
1202
-    The default is to center the text above the thumbnails.  This option will
1203
-    align the titles either to the left (west) or right (east).  Aligning west
1204
-    gives more space to the titles.  Aligning east also does so, and as well
1205
-    will facilitate using \n in your titles to achieve multi line titles.
1206
-<DT><B>-tile-3x1</B>, <B>-tile3x1</B></DT><DD>
1207
-    Use a montage tile of 3x1 instead of the usual 2x2 for 3 videos
1208
-    ie.
1209
-<P></P>
1210
-    [movie1] [movie2] [movie3] instead of:
1211
-<P></P>
1212
-    [movie1] [movie2]
1213
-<P></P>
1214
-    [movie3]
1215
-<P></P>
1216
-    This option only comes into play if the number of videos supplied equals 3
1217
-    Otherwise it will be silently ignored. Not used for -showcase-* style.
1218
-<DT><B>-tile-4x1</B>, <B>-tile4x1</B></DT><DD>
1219
-    Same as <B>-tile-3x1</B> above, except use tile of 4x1. (one row of 4 videos)
1220
-<DT>**-thumb-columns 3|4</DT><DD>
1221
-    Same as <B>-tile-3x1</B> and tile-4x1** above, except it accepts either '3'
1222
-    (1 row of 3 thumbs), or '4' (one row of 4 thumbs) as an argument.  This
1223
-    alternative was added to help compact the gui layout.
1224
-<DT><B>-rotate-thumbs</B> DEGREE LIST ( list of degrees, one for each thumb )</DT><DD>
1225
-    Rotate thumbs the given amount in degrees - can be positive or negative.
1226
-    There must be one value for each file given with <B>-files</B>.
1227
-    If the values are not the same distance from zero, the thumbs will be of
1228
-    different sizes as images are necessarily resized *after* rotating.  With
1229
-    the default montage template - this will also resize the titles; with the
1230
-    showcase template the titles will remain the same size. Example:
1231
-<P></P>
1232
-<PRE>
1233
-      -rotate-thumbs -10 10 -10 10 -10  (for 5 files)
1234
-</PRE>
1235
-
1236
-     **Note: this option will not turn a portrait image into a landscape image!
1237
-</DL>
1238
-
1239
-<A NAME="toc18"></A>
1240
-<H2>Dvdauthor options</H2>
1241
-
1242
-<DL>
1243
-<DT><B>-loop</B> PAUSE</DT><DD>
1244
-    Pause in seconds at end of menu.  Use "inf" if you wish indefinite pause.
1245
-    Note: using "inf" with <B>-menu-fade</B> will disable the fadeout portion of
1246
-    the fade.  (default: "inf" for static menu, 10.0 seconds for animated.)
1247
-<DT><B>-playall</B></DT><DD>
1248
-    This option will create a button on the main menu that will allow going
1249
-    right to the 1st title and playing all videos in succession before
1250
-    returning to the main menu.  If doing titlesets you can use this within
1251
-    the <B>-vmgm</B> ... <B>-end-vmgm</B> options to allow playing ALL titlesets.
1252
-    (If you want also to have a playall button in each titleset you could use
1253
-    this option between each <B>-titleset</B> ... <B>-end-titleset</B> option or put
1254
-    it outside of the vmgm and titlset options as a global option.
1255
-<DT><B>-videos-are-chapters</B></DT><DD>
1256
-    A button will be made on the main menu for each video, which you can use as
1257
-    a chapter button.  Selecting any video will play them all in order
1258
-    starting with the selected one.
1259
-<DT><B>-chain-videos</B> NUM | N1-NN</DT><DD>
1260
-    Without options this will chain all videos together so they play
1261
-    sequentially without returning to the main menu, except for the last, which
1262
-    will return.  You can also specify which videos you want to behave this way
1263
-    by number or by a range. ( ie. <B>-chain-videos</B> 1 2 4-6 ).
1264
-<DT><B>-subtitle-lang</B> "lang1 lang2 . . ."</DT><DD>
1265
-    This allows selectable subtitles in the DVD, assuming you have optional
1266
-    subtitles muxed into your videos.  Use 2 character language codes.
1267
-<DT><B>-audio-channel</B> "Video1_track Video2_track Video3_track . . ."</DT><DD>
1268
-    "VideoN_track" is the track number to use in a multi-track (multi-language)
1269
-    mpeg: usually something like <B>-audio-channel</B> "1 0 1".  The 1st track is
1270
-    0, 2nd is 1 . . . etc.  If the tracks are 0. English 1.French, then the
1271
-    above would make French the audio language on Video1 and Video3, and
1272
-    English the audio language on Video2.  You can check the mpeg with
1273
-    "mplayer -v . . .".
1274
-<DT><B>-audio-lang</B> LANGUAGE CODES</DT><DD>
1275
-    Identify the audio tracks on the DVD.  These language codes are used for
1276
-    each video in the titleset.  When you use the audio button on your DVD
1277
-    remote the language name is displayed.  Example: <B>-audio-lang</B> en fr
1278
-<DT><B>-aspect</B> 4:3|16:9</DT><DD>
1279
-    This will output a &lt;video aspect WIDTH:HEIGHT /&gt; tag for the dvdauthor
1280
-    xml file.  It will affect all videos in the titleset.  Example:
1281
-<P></P>
1282
-<PRE>
1283
-      -aspect 16:9
1284
-</PRE>
1285
-
1286
-<DT><B>-widescreen</B> nopanscan|noletterbox [nopanscan]</DT><DD>
1287
-    This will output a &lt;video widescreen=nopanscan /&gt; tag (for example)
1288
-    for the dvdauthor xml file.  It will affect all videos in the titleset. Use
1289
-    in conjunction with <B>-aspect</B> if your dvd player is cropping your videos.
1290
-    Example:
1291
-<P></P>
1292
-<PRE>
1293
-      -aspect 16:9 -widescreen
1294
-</PRE>
1295
-
1296
-<DT><B>-quick-nav</B></DT><DD>
1297
-    This option will allow navigation of a menu with more than one titleset by
1298
-    using the left and right arrow keys of your DVD remote.  When you press
1299
-    this key the highlight will go the next or previous title.  If you are at
1300
-    the end of a titleset the right key will go to the next titleset.  If you
1301
-    are at the beginning of a titleset, the left key will go to the previous
1302
-    titleset.  If no next or previous titleset it will cycle to the end or
1303
-    beginning of the titlesets.
1304
-<DT><B>-outlinewidth</B>, <B>-outline-width</B> WIDTH</DT><DD>
1305
-    For spumux outlinewidth variable.  If there is a large gap between words in
1306
-    a text button, this option may help.
1307
-<DT><B>-video-pause</B> PAUSE (single value or list)</DT><DD>
1308
-    The pause in seconds after playing a video title.  This is useful for
1309
-    slideshows: the 'slide' will remain on the screen for this length of time.
1310
-    If you have grouped videos you should probably not pause the videos that
1311
-    have a grouped title after it, but instead see <B>-grouped-video-pause</B>.
1312
-    Note: if you provide a list of values they must be one for each video.
1313
-<DT><B>-group-video-pause</B> PAUSE (single value or list)</DT><DD>
1314
-    The pause in seconds after a grouped video plays.  If you wish to pause
1315
-    after the whole group finishes, then only use a value greater than zero
1316
-    for the last video in the group.  If providing a list of values they must
1317
-    equal the number of grouped videos.
1318
-</DL>
1319
-
1320
-<A NAME="toc19"></A>
1321
-<H2>Usage notes</H2>
1322
-
1323
-<P>
1324
-The argument given to various *-font options that set the font to use must be
1325
-one of the fonts listed by the command 'convert -list type'. Please note that
1326
-many of your installed fonts may not be available; if you want to maximize the
1327
-number of fonts available to todisc, download and run
1328
-<A HREF="http://www.cit.gu.edu.au/~anthony/anthony.html">Anthony Thyssen's</A>
1329
-<A HREF="http://www.imagemagick.org/Usage/scripts/imagick_type_gen">imagick_type_gen</A>
1330
-script and run it like this:
1331
-imagick_type_gen &gt; ~/.magick/type.xml.
1332
-If that doesn't work, try imagick_type_gen &gt; ~/.magick/type.mgk.
1333
-</P>
1334
-<P>
1335
-Or you can specify a ttf font file directly to the *-font options if you don't
1336
-want to install fonts to ImageMagick.
1337
-</P>
1338
-<P>
1339
-The *-stroke options in todisc are not a stroke in the sense that ImageMagick
1340
-uses the term, but rather a font shadow (the text is drawn twice)  To get a
1341
-truer Imagemagick -stroke try something like:
1342
--title-font-deco "-stroke black" (or -titles-font-deco "-stroke black").  The
1343
-<B>-fontdeco</B> option is quite flexible and takes a lot of ImageMagick's
1344
-<I>convert</I> options. Please refer to the tovid
1345
-<A HREF="http://tovid.wikia.com/wiki/Making_a_DVD_with_text_menus">wiki</A> and Anthony
1346
-Thyssen's guide [<A HREF="http://www.imagemagick.org/Usage">http://www.imagemagick.org/Usage</A>] for further explanation and examples.
1347
-</P>
1348
-
1349
-<A NAME="toc20"></A>
1350
-<H1>Command:mpg</H1>
1351
-
1352
-<P>
1353
-<B>tovid mpg</B> converts arbitrary video files into (S)VCD/DVD-compliant
1354
-MPEG format, suitable for burning to CD/DVD-R for playback on a
1355
-standalone DVD player.
1356
-</P>
1357
-
1358
-<A NAME="toc21"></A>
1359
-<H2>Usage</H2>
1360
-
1361
-<P>
1362
-<B>tovid mpg</B> [<I>OPTIONS</I>] <B>-in</B> <I>INFILE</I> <B>-out</B> <I>OUTPREFIX</I>
1363
-</P>
1364
-<P>
1365
-Where <I>INFILE</I> is any multimedia video file, and <I>OUTPREFIX</I> is what
1366
-you want to call the output file, minus the file extension. <I>OPTIONS</I>
1367
-are additional customizations, described below.
1368
-</P>
1369
-<P>
1370
-By default, you will (hopefully) end up with an NTSC DVD-compliant
1371
-MPEG-2 video file; if you burn this file to a DVD-R, it should be
1372
-playable on most DVD players.
1373
-</P>
1374
-<P>
1375
-For example:
1376
-</P>
1377
-
1378
-<DL>
1379
-<DT><CODE>tovid mpg -in foo.avi -out foo_encoded</CODE></DT><DD>
1380
-    Convert 'foo.avi' to NTSC DVD format, saving to 'foo_encoded.mpg'.
1381
-<P></P>
1382
-<DT><CODE>tovid mpg -pal -vcd foo.avi -out foo_encoded</CODE></DT><DD>
1383
-    Convert 'foo.avi' to PAL VCD format, saving to 'foo_encoded.mpg'.
1384
-</DL>
1385
-
1386
-<A NAME="toc22"></A>
1387
-<H2>Basic options</H2>
1388
-
1389
-<DL>
1390
-<DT><B>-v</B>, <B>-version</B></DT><DD>
1391
-    Print tovid version number only, then exit.
1392
-<DT><B>-quiet</B></DT><DD>
1393
-    Reduce output to the console.
1394
-<DT><B>-fake</B></DT><DD>
1395
-    Do not actually encode; only print the commands (mplayer, mpeg2enc etc.)
1396
-    that would be executed. Useful in debugging; have tovid give you the
1397
-    commands, and run them manually.
1398
-<DT><B>-ffmpeg</B></DT><DD>
1399
-    Use ffmpeg for video encoding, instead of mplayer/mpeg2enc. Try this if
1400
-    you have any problems with the default encoding method. Using this option,
1401
-    encoding will be considerably faster. It can do almost everything that 
1402
-    mpeg2enc does such as -filters and -subtitles by using a pipe from mplayer
1403
-    though using these options will make encoding somewhat slower. The 
1404
-    exceptions are some special options like -kvcd* -bdvd where you will still
1405
-    need to use the default mpeg2enc option.
1406
-</DL>
1407
-
1408
-<H3>Television standards</H3>
1409
-
1410
-<DL>
1411
-<DT><B>-ntsc</B></DT><DD>
1412
-    NTSC format video (USA, Americas) (default)
1413
-<DT><B>-ntscfilm</B></DT><DD>
1414
-    NTSC-film format video
1415
-<DT><B>-pal</B></DT><DD>
1416
-    PAL format video (Europe and others)
1417
-</DL>
1418
-
1419
-<H3>Formats</H3>
1420
-
1421
-<P>
1422
-Standard formats, should be playable in most DVD players:
1423
-</P>
1424
-
1425
-<DL>
1426
-<DT><B>-dvd</B></DT><DD>
1427
-    (720x480 NTSC, 720x576 PAL) DVD-compatible output (default)
1428
-<DT><B>-half-dvd</B></DT><DD>
1429
-    (352x480 NTSC, 352x576 PAL) Half-D1-compatible output
1430
-<DT><B>-svcd</B></DT><DD>
1431
-    (480x480 NTSC, 480x576 PAL) Super VideoCD-compatible output
1432
-<DT><B>-dvd-vcd</B></DT><DD>
1433
-    (352x240 NTSC, 352x288 PAL) VCD-on-DVD output
1434
-<DT><B>-vcd</B></DT><DD>
1435
-    (352x240 NTSC, 352x288 PAL) VideoCD-compatible output
1436
-</DL>
1437
-
1438
-<P>
1439
-Non-standard formats, playable in some DVD players:
1440
-</P>
1441
-
1442
-<DL>
1443
-<DT><B>-kvcd</B></DT><DD>
1444
-    (352x240 NTSC, 352x288 PAL) KVCD-enhanced long-playing video CD
1445
-<DT><B>-kdvd</B></DT><DD>
1446
-    (720x480 NTSC, 720x576 PAL) KVCD-enhanced long-playing DVD
1447
-<DT><B>-kvcdx3</B></DT><DD>
1448
-    (528x480 NTSC, 520x576 PAL) KVCDx3 specification
1449
-<DT><B>-kvcdx3a</B></DT><DD>
1450
-    (544x480 NTSC, 544x576 PAL) KVCDx3a specification (slightly wider)
1451
-<DT><B>-bdvd</B></DT><DD>
1452
-    (720x480 NTSC, 720x576 PAL) BVCD-enhanced long-playing DVD
1453
-</DL>
1454
-
1455
-<P>
1456
-See <A HREF="http://kvcd.net/">kvcd.net</A> for details on the KVCD specification. Please
1457
-note that KVCD ("K Video Compression Dynamics") is the name of a compression
1458
-scheme that can be applied to any MPEG-1 or MPEG-2 video, and has little to
1459
-do with VCD ("Video Compact Disc"), which is the name of a standard video disc
1460
-format.
1461
-</P>
1462
-
1463
-<A NAME="toc23"></A>
1464
-<H2>Advanced options</H2>
1465
-
1466
-<H3>Aspect ratios</H3>
1467
-
1468
-<P>
1469
-tovid automatically determines aspect ratio of the input video by playing it in
1470
-mplayer. If your video plays with correct aspect in mplayer, you should not
1471
-need to override the default tovid behavior.
1472
-</P>
1473
-<P>
1474
-If mplayer does not play your video with correct aspect, you may provide an
1475
-explicit aspect ratio in one of several ways:
1476
-</P>
1477
-
1478
-<DL>
1479
-<DT><B>-full</B></DT><DD>
1480
-    Same as <B>-aspect 4:3</B>
1481
-<DT><B>-wide</B></DT><DD>
1482
-    Same as <B>-aspect 16:9</B>
1483
-<DT><B>-panavision</B></DT><DD>
1484
-    Same as <B>-aspect 235:100</B>
1485
-<DT><B>-aspect</B> <I>WIDTH</I><B>:</B><I>HEIGHT</I></DT><DD>
1486
-    Custom aspect, where <I>WIDTH</I> and <I>HEIGHT</I> are integers.
1487
-</DL>
1488
-
1489
-<P>
1490
-The above are the intended INPUT aspect ratio. tovid chooses an optimal output
1491
-aspect ratio for the selected disc format (VCD, DVD, etc.) and does the
1492
-appropriate letterboxing or anamorphic scaling. Use <B>-widetv</B> to encode
1493
-for a widescreen monitor or TV.
1494
-</P>
1495
-
1496
-<H3>Video stream options</H3>
1497
-
1498
-<DL>
1499
-<DT><B>-quality</B> <I>NUM</I> (default 6)</DT><DD>
1500
-    Desired output quality, on a scale of 1 to 10, with 10 giving the best
1501
-    quality at the expense of a larger output file. Default is 6. Output size
1502
-    can vary by approximately a factor of 4 (that is, <B>-quality 1</B> output
1503
-    can be 1/4 the size of <B>-quality 10</B> output). Your results may vary.
1504
-    WARNING: With <B>-quality 10</B>, the output bitrate may be too high for
1505
-    your hardware DVD player to handle. Stick with 9 or lower unless you
1506
-    have phenomenally good eyesight.
1507
-<P></P>
1508
-    At present, this option affects both output bitrate and quantization (but
1509
-    may, in the future, affect other quality/size-related attributes). Use
1510
-    <B>-vbitrate</B> if you want to explicitly provide a maximum bitrate.
1511
-<P></P>
1512
-<DT><B>-vbitrate</B> <I>NUM</I></DT><DD>
1513
-    Maximum bitrate to use for video (in kbits/sec). Must be within allowable
1514
-    limits for the given format. Overrides default values. Ignored for VCD,
1515
-    which must be constant bitrate.
1516
-<P></P>
1517
-<DT><B>-interlaced</B></DT><DD>
1518
-    Do interlaced encoding of the input video (top fields first). Use this
1519
-    option if your video is  interlaced, and you want to preserve as much
1520
-    picture quality as possible. This option is ignored for VCD, which
1521
-    doesn't support it.
1522
-<P></P>
1523
-    You can tell your source video is interlaced by playing it, and pausing
1524
-    during a scene with horizontal motion; if you see a "comb" effect at the
1525
-    edges of objects in the scene, you have interlaced video. Use this option
1526
-    to encode it properly.
1527
-<P></P>
1528
-    If you would prefer to have output in progressive format, use
1529
-    <B>-progressive</B>. If you have a DV camera, use <B>-interlaced_bf</B> since
1530
-    DV footage is generally bottom fields first.
1531
-<P></P>
1532
-<DT><B>-interlaced_bf</B></DT><DD>
1533
-    Do interlaced encoding of the input video (bottom fields first).
1534
-<P></P>
1535
-<DT><B>-deinterlace</B>, <B>-progressive</B></DT><DD>
1536
-    Convert interlaced source video into progressive output video. Because
1537
-    deinterlacing works by averaging fields together, some picture quality is
1538
-    invariably lost. Uses an adaptive kernel deinterlacer (kerndeint), or,
1539
-    if that's not available, the libavcodec deinterlacer (lavcdeint).
1540
-<P></P>
1541
-<DT><B>-mkvsub</B> <I>LANG</I> (EXPERIMENTAL)</DT><DD>
1542
-    Attempt to encode an integrated subtitle stream (such as may be found in
1543
-    Matroska .mkv files) in the given language code (eng, jpn, etc.) May work
1544
-    for other formats.
1545
-<P></P>
1546
-<DT><B>-autosubs</B></DT><DD>
1547
-    Automatically include subtitle files with the same name as the input video.
1548
-<P></P>
1549
-<DT><B>-subtitles</B> <I>FILE</I></DT><DD>
1550
-    Get subtitles from <I>FILE</I> and encode them into the video.  WARNING: This
1551
-    hard-codes the subtitles into the video, and you cannot turn them off while
1552
-    viewing the video. By default, no subtitles are loaded. If your video is
1553
-    already compliant with the chosen output format, it will be re-encoded to
1554
-    include the subtitles. This works with both -ffmpeg and the default,
1555
-    mpeg2enc.
1556
-<P></P>
1557
-<DT><B>-dvd-subtitles</B>, <B>-dvdsubs</B> | <I>FILE</I></DT><DD>
1558
-    Get subtitles from <I>FILE(S)</I> and add them <B>as a subtitle stream</B> into the
1559
-    video.  This allows selectable subtitles on your DVD. You can use more than
1560
-    one file for multiple languages. Be sure to use the -subtitle-lang option
1561
-    in 'tovid disc' so the name of the language will show up on the DVD instead
1562
-    of 'UNKNOWN' or similar
1563
-<P></P>
1564
-<DT><B>-dvdsubs-only</B></DT><DD>
1565
-    Use this if you have an already complient MPEG and wish to add a subtitle
1566
-    stream without re-encoding, using <B>-dvdsubs</B> ,
1567
-<P></P>
1568
-<DT><B>-dvdsubs-fontsize</B> <I>NUM</I> [18]</DT><DD>
1569
-    The pointsize in pixels for DVD selectable subtitles. To affect this for
1570
-    hard-coded subtitles ( <B>-subtitles</B> ) you will need to pass options to
1571
-    the player via <B>-mplayeropts</B> or <B>-mpvopts</B>.
1572
-<P></P>
1573
-<DT><B>-type</B> {live|animation|bw}</DT><DD>
1574
-    Optimize video encoding for different kinds of video. Use 'live' (default)
1575
-    for live-action video, use 'animation' for cartoons or anime, and 'bw' for
1576
-    black-and-white video.  This option currently only has an effect with
1577
-    KVCD/KSVCD output formats; other formats may support this in the future.
1578
-<P></P>
1579
-<DT><B>-safe</B> <I>PERCENT</I></DT><DD>
1580
-    Fit the video within a safe area defined by <I>PERCENT</I>. For example,
1581
-    <B>-safe 90%</B> will scale the video to 90% of the width/height of the output
1582
-    resolution, and pad the edges with a black border. Use this if some of the
1583
-    picture is cut off when played on your TV.  The percent sign is optional.
1584
-<P></P>
1585
-<DT><B>-filters</B> {none,denoise,deblock,contrast,all} (default none)</DT><DD>
1586
-    Apply post-processing filters to enhance the video. If your input video is
1587
-    very high quality, use 'none'. If your input video is grainy, use 'denoise';
1588
-    if it looks washed out or faded, use 'contrast'. You can use multiple
1589
-    filters separated by commas. To apply all filters, use 'all'. This works
1590
-    with both mpeg2enc and -ffmpeg.
1591
-<P></P>
1592
-<DT><B>-fps</B> <I>RATIO</I></DT><DD>
1593
-    Force input video to be interpreted as <I>RATIO</I> frames per second.  May be
1594
-    necessary for some ASF, MOV, or other videos. <I>RATIO</I> should be an
1595
-    integer ratio such as "24000:1001" (23.976fps), "30000:1001" (29.97fps), or
1596
-    "25:1" (25fps). This option is temporary, and may disappear in future
1597
-    releases. (Hint: To convert a decimal like 23.976 to an integer ratio, just
1598
-    multiply by 1000, i.e. 23976:1000)
1599
-<P></P>
1600
-<DT><B>-crop</B> <I>WIDTH</I>:<I>HEIGHT</I>:<I>X</I>:<I>Y</I></DT><DD>
1601
-    Crop a portion of the video <I>WIDTH</I> by <I>HEIGHT</I> in size, with the
1602
-    top-left corner at <I>X</I>, <I>Y</I>.
1603
-<P></P>
1604
-<DT><B>-widetv</B></DT><DD>
1605
-    Always encode to 16:9 widescreen (only supported by <B>-dvd</B>, <B>-kdvd</B>,
1606
-    <B>-bdvd</B>), for optimal viewing on a widescreen monitor or TV.
1607
-</DL>
1608
-
1609
-<H3>Audio stream options</H3>
1610
-
1611
-<DL>
1612
-<DT><B>-normalize</B></DT><DD>
1613
-    Analyze the audio stream and then normalize the volume of the audio.
1614
-    This is useful if the audio is too quiet or too loud, or you want to
1615
-    make volume consistent for a bunch of videos. Similar to running
1616
-    normalize without any parameters. The default is -12dB average level
1617
-    with 0dB gain.
1618
-<P></P>
1619
-<DT><B>-amplitude</B> <I>NUM</I>[dB]</DT><DD>
1620
-    In addition to analyzing and normalizing, apply the gain to the audio
1621
-    such that the 'average' (RMS) sound level is <I>NUM</I>. Valid values
1622
-    range 0.0 - 1.0, with 0.0 being silent and 1.0 being full scale. Use
1623
-    <I>NUM</I>dB for a decibel gain below full scale (the default without
1624
-    -amplitude is -12dB).
1625
-<P></P>
1626
-<DT><B>-abitrate</B> <I>NUM</I></DT><DD>
1627
-    Encode audio at <I>NUM</I> kilobits per second.  Reasonable values include
1628
-    128, 224, and 384. The default is 224 kbits/sec, good enough for most
1629
-    encodings. The value must be within the allowable range for the chosen disc
1630
-    format; Ignored for VCD, which must be 224.
1631
-<P></P>
1632
-<DT><B>-audiotrack</B> <I>NUM</I></DT><DD>
1633
-    Encode the given audio track, if the input video has multiple audio tracks.
1634
-    <I>NUM</I> is <I>1</I> for the first track, <I>2</I> for the second, etc. You may
1635
-    also provide a list of tracks, separated by spaces or commas, for example
1636
-    <B>-audiotrack 3,1,2</B>. Use <B>tovid id</B> on your source video to determine
1637
-    which audio tracks it contains.
1638
-<P></P>
1639
-<DT><B>-downmix</B></DT><DD>
1640
-    Encode all audio tracks as stereo.  This can save space on your DVD if
1641
-    your player only does stereo.  The default behavior of tovid is to use
1642
-    the original number of channels in each track.  For aac audio, downmixing
1643
-    is not possible: tovid runs a quick 1 frame test to try to downmix the
1644
-    input track with the largest number of channels, and if it fails then it
1645
-    will revert to the default behavior of using the original channels.
1646
-</DL>
1647
-
1648
-<H3>Other options</H3>
1649
-
1650
-<DL>
1651
-<DT><B>-config</B> <I>FILE</I></DT><DD>
1652
-    Read configuration from <I>FILE</I>, containing 'tovid' alone on the first
1653
-    line, and free-formatted (whitespace-separated) tovid command-line options
1654
-    on remaining lines.
1655
-<P></P>
1656
-<DT><B>-force</B></DT><DD>
1657
-    Force encoding of already-compliant video or audio streams.
1658
-<P></P>
1659
-<DT><B>-overwrite</B></DT><DD>
1660
-    Overwrite any existing output files (with the same name as the given
1661
-    <B>-out</B> option).
1662
-<P></P>
1663
-<DT><B>-priority</B> {low|medium|high}</DT><DD>
1664
-    Sets the main encoding process to the given priority. With high priority,
1665
-    it may take other programs longer to load and respond. With lower priority,
1666
-    other programs will be more responsive, but encoding may take 30-40%
1667
-    longer.  The default is high priority.
1668
-<P></P>
1669
-<DT><B>-discsize</B> <I>NUM</I></DT><DD>
1670
-    When encoding, tovid automatically splits the output file into several
1671
-    pieces if it exceeds the size of the target media. This option sets the
1672
-    desired target DVD/CD-R size to <I>NUM</I> mebibytes (MiB, 2^20). By default,
1673
-    splitting occurs at 700 for CD, 4300 for DVD. Use higher values at your
1674
-    own risk. Use 650 or lower if you plan to burn to smaller-capacity CDs.
1675
-    Doesn't work with the <B>-ffmpeg</B> option.
1676
-<P></P>
1677
-<DT><B>-fit</B> <I>NUM</I></DT><DD>
1678
-    Fit the output file into <I>NUM</I> MiB. Rather than using default (or
1679
-    specified) video bitrates, tovid will calculate the correct video bitrate
1680
-    that will limit the final output size to <I>NUM</I> MiB. This is different
1681
-    than <B>-discsize</B>, which cuts the final file into <I>NUM</I> MiB pieces.
1682
-    <B>-fit</B> makes sure that the file never exceeds <I>NUM</I> MiB. This works
1683
-    with <B>-ffmpeg</B>, but not with <B>-vcd</B> since VCDs have a standardized
1684
-    constant bitrate.
1685
-<P></P>
1686
-<DT><B>-parallel</B></DT><DD>
1687
-    Perform ripping, encoding, and multiplexing processes in parallel using
1688
-    named pipes. Maximizes CPU utilization and minimizes disk usage. Note that
1689
-    this option simply does more tasks simultaneously, in order to make better
1690
-    use of available CPU cycles; it's unrelated to multi-CPU processing (which
1691
-    is done automatically anyway). Has no effect when <B>-ffmpeg</B> is used.
1692
-<P></P>
1693
-<DT><B>-update</B> <I>SECS</I></DT><DD>
1694
-    Print status updates at intervals of <I>SECS</I> seconds. This affects how
1695
-    regularly the progress-meter is updated. The default is once every five
1696
-    seconds.
1697
-<P></P>
1698
-<DT><B>-mpv</B></DT><DD>
1699
-    Use mpv instead of mplayer. This option is experimental.
1700
-<P></P>
1701
-<DT><B>-mplayeropts</B> <I>OPTIONS</I></DT><DD>
1702
-    Append <I>OPTIONS</I> to the mplayer command run during video encoding.  Use
1703
-    this if you want to add specific video filters (documented in the mplayer
1704
-    manual page). Overriding some options will cause encoding to fail, so use
1705
-    this with caution!
1706
-<P></P>
1707
-<DT><B>-mpvopts</B> <I>OPTIONS</I></DT><DD>
1708
-    Append <I>OPTIONS</I> to the mpv command run during video encoding.  Use
1709
-    this if you want to add specific video filters (documented in the mplayer
1710
-    or mpv manual page). Overriding some options will cause encoding to fail,
1711
-    so use this with caution!
1712
-<P></P>
1713
-<DT><B>-nofifo</B> (EXPERIMENTAL)</DT><DD>
1714
-    Do not use a FIFO pipe for video encoding. If you are getting "Broken pipe"
1715
-    errors with normal encoding, try this option.  WARNING: This uses lots of
1716
-    disk space (about 2 GB per minute of video).
1717
-<P></P>
1718
-<DT><B>-keepfiles</B></DT><DD>
1719
-    Keep the intermediate files after encoding. Usually, this means the audio
1720
-    and video streams are kept (eg the .ac3 and .m2v files for an NTSC DVD).
1721
-    This doesn't work with -parallel because the intermediate files are named
1722
-    pipes, and not real files.
1723
-<P></P>
1724
-<DT><B>-slice</B> <I>START</I>-<I>END</I></DT><DD>
1725
-    Encode a segment from <I>START</I> to <I>END</I> (in seconds). Only works with
1726
-    -ffmpeg.
1727
-<P></P>
1728
-<DT><B>-from-gui</B></DT><DD>
1729
-    Put makempg into a fully non-interactive state, suitable for calling from
1730
-    a gui.
1731
-<P></P>
1732
-<DT><B>-noask</B></DT><DD>
1733
-    Don't ask questions when choices need to be made. Assume reasonable
1734
-    answers.
1735
-</DL>
1736
-
1737
-<A NAME="toc24"></A>
1738
-<H1>Command:id</H1>
1739
-
1740
-<P>
1741
-<B>tovid id</B> identifies each multimedia video file in a
1742
-list, and reports its compliance with video disc standards such as VCD,
1743
-SVCD, and DVD.
1744
-</P>
1745
-
1746
-<A NAME="toc25"></A>
1747
-<H2>Usage</H2>
1748
-
1749
-<P>
1750
-<B>tovid id</B> [<I>OPTIONS</I>] <I>VIDEO_FILE(s)</I>
1751
-</P>
1752
-<P>
1753
-For example:
1754
-</P>
1755
-
1756
-<DL>
1757
-<DT><CODE>tovid id foo.avi</CODE></DT><DD>
1758
-<DT><CODE>tovid id -tabluar videos/*.mpg</CODE></DT><DD>
1759
-</DL>
1760
-
1761
-<A NAME="toc26"></A>
1762
-<H2>Options</H2>
1763
-
1764
-<DL>
1765
-<DT><B>-terse</B></DT><DD>
1766
-    Print raw video characteristics, no formatting. Helpful when
1767
-    calling from other scripts.
1768
-<P></P>
1769
-<DT><B>-verbose</B></DT><DD>
1770
-    Print extra information from mplayer, tcprobe, and ffmpeg.
1771
-<P></P>
1772
-<DT><B>-accurate</B></DT><DD>
1773
-    Do lengthy play-time estimation by scanning through the entire video file.
1774
-    Use this if the default behavior is giving you inaccurate play times.
1775
-<P></P>
1776
-<DT><B>-fast</B></DT><DD>
1777
-    Skip lengthy play-time estimation, and go with what mplayer reports
1778
-    as being the video duration. Unlike pre-0.32 versions of tovid, this
1779
-    is now the default behavior, and the <B>-fast</B> option doesn't do anything.
1780
-<P></P>
1781
-<DT><B>-tabular</B></DT><DD>
1782
-    Display output in a table format for easier comparison. Most useful
1783
-    when identifying multiple video files.
1784
-<P></P>
1785
-<DT><B>-keepfiles</B></DT><DD>
1786
-    Keep temporary directory for debugging.
1787
-<P></P>
1788
-<DT><B>-isformat</B> [<I>pal-dvd</I>|<I>ntsc-dvd</I>] (same syntax for vcd and svcd)</DT><DD>
1789
-    Check <I>VIDEO_FILE</I> for compliance with the given disc format.
1790
-    If <I>VIDEO_FILE</I> matches the given format, then <B>tovid id</B> reports "true"
1791
-    and exits successfully. Otherwise, <B>tovid id</B> reports "false" and exits
1792
-    with status 1 (failure).  This checks and reports both vcd/svcd/dvd
1793
-    and pal/ntsc.
1794
-<P></P>
1795
-<DT><B>-mpv</B></DT><DD>
1796
-    This option is mainly for testing. If you have only mpv installed instead
1797
-    of mplayer, it is used automatically. With this option, you can have BOTH
1798
-    installed and choose which one to use. (default: mplayer)
1799
-</DL>
1800
-
1801
-<A NAME="toc27"></A>
1802
-<H2>Examples</H2>
1803
-
1804
-<DL>
1805
-<DT><CODE>tovid id -verbose homevideo.avi</CODE></DT><DD>
1806
-    Report everything mplayer, ffmpeg, and transcode can determine about
1807
-    homevideo.avi.
1808
-<P></P>
1809
-<DT><CODE>tovid id -isformat dvd homevideo.mpg</CODE></DT><DD>
1810
-    Check to see if homevideo.mpg is compliant with the DVD standard.
1811
-</DL>
1812
-
1813
-<A NAME="toc28"></A>
1814
-<H1>Command:dvd</H1>
1815
-
1816
-<P>
1817
-<B>tovid dvd</B> takes a DVD directory as generated by tovid with 'tovid disc' or
1818
-one of the GUI frontends like 'tovid gui' or 'tovid titlesets' and burns
1819
-it to appropriate media.  This will also work if the DVD directory is
1820
-generated by the dvdauthor backend that tovid also uses.
1821
-</P>
1822
-<P>
1823
-Running this program may slow down your other applications, due to intense
1824
-disk activity.
1825
-</P>
1826
-
1827
-<A NAME="toc29"></A>
1828
-<H2>Usage</H2>
1829
-
1830
-<P>
1831
-<B>tovid dvd</B> [<I>OPTIONS</I>] <I>DVD_DIR</I>
1832
-</P>
1833
-<P>
1834
-For example:
1835
-</P>
1836
-
1837
-<DL>
1838
-<DT><CODE>tovid dvd /path/to/DVD/directory</CODE></DT><DD>
1839
-</DL>
1840
-
1841
-<A NAME="toc30"></A>
1842
-<H2>Options</H2>
1843
-
1844
-<DL>
1845
-<DT><B>-burn</B></DT><DD>
1846
-    Burn a DVD file-system in <I>DVD_DIR</I> (must contain a VIDEO_TS folder).
1847
-    This option is currently not necessary as the makedvd script ONLY burns
1848
-    now that legacy scripts like makexml have been removed.  Left for
1849
-    compatibility only.
1850
-<P></P>
1851
-<DT><B>-eject</B></DT><DD>
1852
-    Eject the DVD tray after burning is complete. By default, the DVD is not
1853
-    ejected.
1854
-<P></P>
1855
-<DT><B>-device</B> <I>DEVICE</I> (default /dev/dvdrw)</DT><DD>
1856
-    Burn the disc image to <I>DEVICE</I>, the Linux device file-system
1857
-    name of your DVD-recorder. Common examples might be /dev/dvdrw,
1858
-    /dev/scd1, and /dev/hdc. You can also use a bus/id/lun triple
1859
-    such as ATAPI:0,1,0
1860
-<P></P>
1861
-<DT><B>-speed</B> <I>NUM</I> (default 1)</DT><DD>
1862
-    Burn disc at speed <I>NUM</I>.
1863
-<P></P>
1864
-<DT><B>-label</B> <I>DISC_LABEL</I></DT><DD>
1865
-    Uses <I>DISC_LABEL</I> as the volume ID. This appears as the mount
1866
-    name of the disc on some computer platforms. Must be &lt;=32
1867
-    alphanumeric digits without spaces.
1868
-<P></P>
1869
-<DT><B>-quiet</B></DT><DD>
1870
-    Limit output to essential messages.
1871
-<P></P>
1872
-<DT><B>-noask</B></DT><DD>
1873
-    Don't ask interactive questions and assume answers that will continue
1874
-    execution.
1875
-</DL>
1876
-
1877
-<P>
1878
-    After burning, the DVD can be previewed by calling:
1879
-    <I><B>xine</B> dvd:/path/to/output/directory</I>
1880
-    or:
1881
-    <I><B>vlc</B> /path/to/output/directory</I>
1882
-</P>
1883
-
1884
-<A NAME="toc31"></A>
1885
-<H1>Command:chapters</H1>
1886
-
1887
-<P>
1888
-<B>tovid chapters</B> will start a GUI using mplayer to set chapter points in a
1889
-video.  If the video plays through and you want to add more chapters you can
1890
-press the play button again, but remember that new chapter points will be
1891
-appended (in correct sequential order).  It will display the resulting chapter
1892
-points, and also output to a terminal (useful for scripts).  As well it will
1893
-give the option of saving the chapters string to a text file.
1894
-</P>
1895
-<P>
1896
-Note that the 'tovid gui' now features a similar widget when you press the
1897
-chapters button on the opening page.
1898
-</P>
1899
-
1900
-<A NAME="toc32"></A>
1901
-<H2>Examples</H2>
1902
-
1903
-<DL>
1904
-<DT><CODE>tovid chapters foo.avi</CODE></DT><DD>
1905
-<P></P>
1906
-<DT><CODE>chapters=$(tovid chapters /home/grepper/videos/foo.avi)</CODE></DT><DD>
1907
-</DL>
1908
-
1909
-<A NAME="toc33"></A>
1910
-<H1>CONTACT</H1>
1911
-
1912
-<P>
1913
-For further assistance, contact information, forum and IRC links,
1914
-please refer to the <A HREF="http://tovid.wikia.com/">tovid homepage</A>.
1915
-</P>
1916
-
1917
-<!-- html code generated by txt2tags 2.6 (http://txt2tags.org) -->
1918
-<!-- cmdline: txt2tags -t html -\-toc -\-toc-level 2 docs/src/en/tovid.t2t -->
1919
-</BODY></HTML>
1920
tovid-0.35.0.tar.gz/docs/src/en/tovid.wiki Deleted
1665
 
1
@@ -1,1663 +0,0 @@
2
-'''tovid manual'''
3
-
4
-
5
-
6
-
7
-----
8
-
9
-__TOC__
10
-
11
-----
12
-
13
-
14
-== Name ==
15
-
16
-tovid: Make DVDs from video files
17
-
18
-== Description ==
19
-
20
-'''tovid''' is a command-line tool for creating DVDs. It can encode your video
21
-files to DVD-compliant MPEG format, generate simple or complex DVD menus,
22
-author and burn a ready-to-watch DVD, with just a few shell commands. A
23
-graphical interface is also provided to make the process even easier.
24
-
25
-'''NOTE''': As of tovid 0.35, the legacy scripts '''makemenu''' and '''makexml'''
26
-have been removed and no longer appear in this manpage.
27
-All of their functions and more can be done with the 'tovid disc' command,
28
-(todisc script). See '''Command:disc''' and the [http://tovid.wikia.com wiki]
29
-for more info.
30
-
31
-Also note that as of tovid 0.32, this is the only manual page provided by tovid.
32
-There is now a single executable frontend to all functionality in the suite, so
33
-if you were expecting to find manpages for '''todisc''', '''idvid''', '''makempg'''
34
-and their kin, they can all be found in the '''tovid''' manpage you are reading now.
35
-And yes, this makes for a pretty large manual page. If you are viewing this
36
-manpage from the command-line '''man''' utility, which normally pages through the
37
-'''less''' utility, you can skip to a section by searching with the '''/''' key,
38
-followed by a '''^''' to match the given section name. For example, to skip to
39
-the '''mpg''' command, type '''/^Command:mpg'''. See '''man less''' for more on how
40
-to navigate.
41
-
42
-== Usage ==
43
-
44
-'''tovid''' ''COMMAND'' [''OPTIONS'']
45
-
46
-Where ''COMMAND'' is one of the following:
47
-
48
-    Main Commands
49
-
50
-; '''disc'''
51
-: Encode, make menus, author, burn. (was '''todisc'''. See '''Command:disc''')
52
-; '''gui'''
53
-: Start the tovid GUI (was '''todiscgui'''. See '''Command:gui''')
54
-; '''titlesets'''
55
-: A GUI wizard for multiple titlesets. (new: See '''Command:titlesets''')
56
-
57
-    Helper Commands
58
-
59
-; '''mpg'''
60
-: Encode videos to MPEG format (was '''tovid'''. See '''Command:mpg''')
61
-; '''dvd'''
62
-: Author and/or burn a DVD (was '''makedvd'''. See '''Command:dvd''')
63
-; '''id'''
64
-: Identify one or more video files (was '''idvid'''. See '''Command:id''')
65
-; '''chapters'''
66
-: A GUI using mplayer for setting chapter points.  It will return a string of
67
-: chapter points to the terminal, in a format recognized by 'tovid disc'
68
-: (todisc) or by 'tovid gui', for the  '''-chapters''' option.
69
-
70
-The ''OPTIONS'' differ for each command; run '''tovid <command>''' with no
71
-further arguments to get help on a command, and what options it expects.
72
-
73
-== Configuration ==
74
-
75
-Two configuration files are created the first time you run tovid:
76
-
77
-; '''~/.tovid/preferences'''
78
-: Defines working directory for all scripts.
79
-: You can define the output directory for makempg here.
80
-: The 'ffmpeg' executable can be set here: ffmpeg or avconv (TOVID_FFMPEG)
81
-; '''~/.tovid/tovid.ini'''
82
-: Includes command-line options that should be passed to the various
83
-: '''tovid''' sub-commands.  Note: each sub-command has its own section,
84
-: starting with the line [sub-command], for example:
85
-<pre>
86
-    [disc]
87
-    ; -no-warn
88
-    -static
89
-    -no-ask
90
-</pre>
91
-
92
-
93
-Edit these files if you wish to change your configuration.
94
-
95
-The following environment variables are also honoured:
96
-
97
-<pre>
98
-    TOVID_HOME (directory containing preferences: ~/.tovid)
99
-    TOVID_WORKING_DIR (working directory for all scripts).
100
-    TOVID_OUTPUT_DIR (output directory for the makempg script).
101
-    TOVID_FFMPEG_CMD (the 'ffmpeg' executable to use: ffmpeg or avconv)
102
-</pre>
103
-
104
-These will override 'TOVID_HOME', 'WORKING_DIR', 'OUTPUT_DIR',
105
-and 'TOVID_FFMPEG' if set in ~/.tovid/preferences.
106
-
107
-== Command:gui ==
108
-
109
-== Usage ==
110
-
111
-'''tovid gui''' [''OPTIONS'']
112
-
113
-'''tovid gui''' starts the graphical user interface (GUI) for tovid. This is
114
-the easiest way to start creating DVDs with tovid. The optional arguments
115
-''OPTIONS'' are any option used by todisc ('tovid disc') which will save
116
-entering it manually, OR the full path to a saved script from the GUI.
117
-You can also combine these, but the script must be the FIRST option
118
-directly after '''tovid gui''' .  (This option to save the contents of your
119
-project allows you to use it as a bash script later, or to reload the
120
-project to continue working with it at another time.)
121
-
122
-'''tovid gui''' will also take the option '''--position''', which denotes the
123
-screen position that the GUI will start at, in the form '+X+Y', similar to
124
-this part of the Xorg -geometry string.
125
-
126
-All help is integrated in the form of tooltips.  You can also see
127
-**Command:disc ** for more detail about the options.  Note: if you wish to use
128
-a GUI to make multiple titlesets on the same DVD use '''*tovid titlesets*''',
129
-which is a wizard that uses the the 'tovid gui. See '''*Command:titlesets*'''.
130
-
131
-Please note that although the interface may seem complex with so many options,
132
-you can create a fully functional DVD with only a few options on the opening
133
-tab of the GUI (select video files and an output name).
134
-
135
-== Command:titlesets ==
136
-
137
-'''tovid titlesets''' will assist in making a DVD with multiple titlesets.  It can
138
-be started without any options, or you can feed it the path to a saved titleset
139
-script as an option.  The option to save a script is also useful as the resulting
140
-script can be run later from a terminal.
141
-
142
-== Command:disc ==
143
-
144
-'''tovid disc''' creates a DVD file-system with optional menus, from a list of
145
-multimedia video files and their titles.  As todisc can function as a master
146
-script, calling other scripts as it needs them, it is the easiest command line
147
-program for creating a DVD from start to finish, including automatically
148
-converting non-compliant videos and prompting to burn at completion.  It can do
149
-animated menus, static thumbnail menus, text-only menus, or author with no menu.
150
-In addition, it can do slideshows, using images as input, and even combine
151
-slideshows with videos.  It supports sub-menus for chapter breaks,
152
-configurable menu style, animated backgrounds and transparency effects.
153
-From simple (no menu) to complex (switched menus and titlesets), you should
154
-be able to do what you want with 'tovid disc'.
155
-
156
-=== Usage ===
157
-
158
-<pre>
159
- tovid disc [OPTIONS] \
160
-    -files <file list> -titles <title list>
161
-    -out mydvd
162
-</pre>
163
-
164
-For example:
165
-
166
-<pre>
167
- $ tovid disc -files File1.mpg File2.mpg File3.mpg \
168
-      -titles "Episode 1" "Episode 2" "Episode 3" \
169
-      -out Season_one
170
-</pre>
171
-
172
-The number of '''-files''' and '''-titles''' must be equal, though if you do not
173
-include any titles '''tovid disc''' will use the basename of the included files
174
-as titles.  If you are doing a slideshow or multiple slideshows, use
175
-'''-slides''' rather than '''-files''' for passing in the images.  You may use
176
--files and -slides more than once to create an ordering in a mixed
177
-slideshows/videos menu.  See Slideshows part of Usage section, below.
178
-
179
-If the input files are not mpeg, you will have the option to auto-encode them.
180
-
181
-General Options
182
-
183
-'''At present there are 2 display arrangements or "templates":'''
184
-
185
-; A. (Default)
186
-: Thumbs will be centred, and as large as space restraints allow.
187
-: 
188
-; B. '''-showcase''' IMAGE|VIDEO
189
-: Produces an arrangement with small buttons on
190
-: the side and the showcase image/video in the centre.  If no IMAGE or VIDEO
191
-: argument is supplied, the central thumb will be omitted.
192
-: 
193
-: Note: '''-textmenu''', '''-quick-menu''' and '''-switched-menus''' are all types
194
-: of showcase style menus.  See descriptions under '''Menu style''' section.
195
-
196
-The '''-titles''' arguments should be double or single quoted, or have the spaces
197
-backslash-escaped. Special characters (like ", !, *, &, ?) may need to be
198
-backslash-escaped.  To include a quoted string within a title, backslash-escape
199
-the quotes.  These titles are used for labelling thumbnails on the main menu,
200
-and for the submenu title for that video.  ( see also '''-submenu-titles''' )
201
-
202
-The '''-showcase''' styles can use longer titles than the default arrangement.
203
-With a showcase style, use: '''-showcase-titles-align west''' to give more space
204
-for the title, or use '''-showcase-titles-align east''' to allow titles of more
205
-than one line.
206
-
207
-The default style can only show about 16 characters (depending on the number
208
-of thumbs, and what '''-titles-font''' and '''-titles-fontsize''' is being used).
209
-If your titles are too long to fit in the label area, you may try using
210
-sub-menus, which can display longer titles, for example:
211
-
212
-<pre>
213
- $ tovid disc -submenus \
214
-      -files file1.mpg file2.mpg ... \
215
-      -titles "Short 1" "Short 2" \
216
-      -submenus \
217
-      -submenu-titles "Long Title One" "Long Title Two" \
218
-      -out foo
219
-
220
-</pre>
221
-
222
-The '''-align''' argument will position both titles and thumbs either south,
223
-north east, west, southwest, northwest, southeast, northeast, subject to
224
-certain constraints of each arrangement. For example a showcase style with
225
-a showcase thumb can only do north|south|center.
226
-
227
-More Examples:
228
-
229
-A text-only menu:
230
-
231
-<pre>
232
- $ tovid disc -textmenu ...
233
-</pre>
234
-
235
-No menu:
236
-
237
-<pre>
238
- $ tovid -nomenu -files file1.mpg file2.mp4 "file 3.avi" -out mydvd
239
-</pre>
240
-
241
-'''Titlesets'''
242
-
243
-A word should be mentioned here about titlesets, which is really just a
244
-hierarchy of menus.  You need to use titlesets, for example, if you have videos
245
-of different resolutions, or otherwise want to arrange videos on separate menus.
246
-If you want to have titlesets you need to put all the options for each titleset
247
-menu you would like to have between '''-titleset''' and '''-end-titleset''' options.
248
-
249
-Additionally, for the main menu (the opening menu that will let you jump to
250
-each titleset), you need to put options between '''-vmgm''' and '''-end-vmgm'''.
251
-You do not use '''-files''' for the opening menu options ('''-vmgm'''), but you
252
-will need as many TITLES after '''-titles''' as you have menus.
253
-
254
-Any options outside the '''-titleset''' '''-end-titleset''' and '''-vmgm'''
255
-'''-end-vmgm''' areas will be global options applying to every titleset.
256
-If a global option is duplicated inside a '''-titleset''' or '''-vmgm''' area, the
257
-global option will be overridden.
258
-
259
-Note: you do not need titlesets for a single menu with chapter break menus, for
260
-that just use '''-submenus''' or '''-ani-submenus'''
261
-
262
-Example of using '''tovid disc''' with titlesets:
263
-
264
-<pre>
265
- $ tovid disc -static -out MY_DVD \
266
-   \
267
-   -titleset \
268
-   -files 1.mpg 2.mpg 3.mpg \
269
-   -titles "Title One" "Title Two" "Title Three" \
270
-   -end-titleset \
271
-   \
272
-   -titleset \
273
-   -files 4.mpg 5.mpg \
274
-   -titles "Title Four" "Title Five" \
275
-   -background foo.jpg \
276
-   -showcase bar.png \
277
-   -end-titleset \
278
-   \
279
-   -vmgm \
280
-   -titles "Season One" "Season Two" \
281
-   -background bg.jpg \
282
-   -bgaudio foo.mp3 \
283
-   -titles-fontsize 20 \
284
-   -end-vmgm
285
-</pre>
286
-
287
-See also '''-titleset''' and '''-vmgm'''
288
-
289
-'''Slideshows'''
290
-
291
-You can also use '''tovid disc''' to make slideshows.  This can either be a single
292
-slideshow, or multiple slideshows on the same menu.
293
-Remember to use '''-slides''' rather than '''-files''' for passing in the
294
-images.  Images can be any filetype that imagemagick supports: for example
295
-JPEG, PNG, GIF, TGA BMP etc.  For a single slideshow do not use '''-titles''':
296
-use -menu-title to set the slideshow title.
297
-
298
-For a single slideshow the default is an animated menu that transitions from
299
-slide to slide.  The default transition type is 'crossfade', which fades each
300
-slide into the next and loops back to the first slide at the end.  If instead
301
-you use '''-static''', then a static 'polaroid stack' menu of all the slides is
302
-created, with a single spumux'ed button for navigating with the enter key.  You
303
-may have to experiment to find out which DVD remote button advances the slides.
304
-Try the 'next chapter'(skip ?) button and the play or enter buttons.
305
-If you want to limit the number of slides in the menu to a subset of all files
306
-entered with '''-slides''', then use '''-menu-slide-total''' INT.  Be sure to use
307
-a long enough audio file for '''-bgaudio''' or set '''-menu-length''' so the menu
308
-is long enough to support the slides plus transitions.
309
-
310
-You can also put multiple slideshows on one menu.  To do this, use
311
-'''-slides IMAGES''' for each slideshow desired.  You can even mix videos
312
-with slideshows by using '''-files''' '''-slides''' '''-titles''' multiple times.
313
-
314
-Example of a single slideshow with an animated menu with transitions:
315
-
316
-<pre>
317
- $ tovid disc -menu-title "Autumn in Toronto" -slides images/*.jpg \
318
-    -menu-slide-total 20 -slide-transition crossfade -bgaudio slideshow.wav \
319
-    -out myslideshow
320
-</pre>
321
-
322
-Example of multiple slideshows on one menu:
323
-
324
-<pre>
325
- $ tovid disc -menu-title "Autumn in Toronto" \
326
-   -slides photos/september/*.jpg \
327
-   -slides photos/october/*.jpg \
328
-   -slides photos/november/*.jpg \
329
-   -tile3x1 -rotate -5 5 -5 -align center \
330
-   -bgaudio background.wav \
331
-   -out myslideshow
332
-</pre>
333
-
334
-Example of mixed videos and slideshows:
335
-
336
-<pre>
337
- $ tovid disc -menu-title "Autumn in Toronto" \
338
-   -files fall_fair.mov \
339
-   -slides  photos/september/*.jpg \
340
-   -files harvest.mpg \
341
-   -slides photos/october/*.jpg \
342
-   -titles "Fall Fair" "September" "Harvest" "October" \
343
-   -background autumn.png \
344
-   -bgaudio bg.mp3 \
345
-   -out myslideshow
346
-</pre>
347
-
348
-See the other slideshow options in the Slideshows options section.
349
-
350
-'''Encoding Options'''
351
-
352
-These are options for reencoding your non-compliant videos.  They are passed
353
-directly to the '''tovid mpg''' command which is invoked by '''tovid disc''' when
354
-non-compliant files are found.  For details, see the '''Command:mpg''' section.
355
-Here is a list of possible options you can pass:
356
-    '''-config''', '''-ntscfilm''', '''-dvd-vcd''', '''-half-dvd''', '''-kvcd''',
357
-    '''-kvcdx3''', '''-kvcdx3a''', '''-kdvd''', '''-bdvd''', '''-704''', '''-normalize''',
358
-    '''-amplitude''', '''-overwrite''', '''-panavision''', '''-force''', '''-fps''',
359
-    '''-vbitrate''', '''-quality''', '''-safe''', '''-crop''', '''-filters''',
360
-    '''-abitrate''', '''-priority''', '''-deinterlace''', '''-progressive''',
361
-    '''-interlaced''', '''-interlaced_bf''', '''-type''', '''-fit''', '''-discsize''',
362
-    '''-parallel''', '''-mkvsub''', '''-autosubs''', '''-subtitles''', '''-update''',
363
-    '''-mplayeropts''', '''-audiotrack''', '''-downmix''', '''-ffmpeg''', '''-nofifo''',
364
-    '''-from-gui''', '''-slice''', '''-quiet''',
365
-    '''-fake''', '''-keepfiles'''
366
-
367
-=== General Options ===
368
-
369
-; '''-keep-files''', '''-keepfiles'''
370
-: Keep all intermediate/temporary files (helps with debugging)
371
-; '''-no-ask''' | '''-noask'''
372
-: Skip all interactive questions.  No preview, automatic re-encoding with
373
-: tovid if needed, no interactive option to use background video for bgaudio.
374
-; '''-no-warn''', '''-nowarn'''
375
-: Don't pause after outputting warning or info messages
376
-; '''-jobs'''
377
-: By default, '''tovid disc''' starts a parallel job for each processor
378
-: detected.  With this option you can manually set the number of jobs.  For
379
-: example if you have a computer with 2 CPUs you can set "-jobs 1" to keep
380
-: one processor free for other things.  At present this applies to the time
381
-: consuming imagemagick loops: you will notice a substantial speedup now if
382
-: you have a multi-cpu system.
383
-; '''-grid'''
384
-: Show a second preview image with a grid and numbers that will help in finding
385
-: coordinates for options that might use them, like '''-text-start'''
386
-; '''-no-confirm-backup'''
387
-: This option is for when your DVD contains images for a slideshow.
388
-: Slideshows are an experimental (but well tested) feature.  Todisc is
389
-: unlikely to overwrite your personal files, but you should take precautions
390
-: and backup your images, as you would with any beta software.  Todisc
391
-: will prompt you to backup your files normally.  If you have already backed
392
-: up your images, use this option to disable the prompt.
393
-: 
394
-: ==Options==
395
-: 
396
-; '''-ntsc'''
397
-: 720x480 output, compatible with NTSC standard (default)
398
-; '''-pal'''
399
-: 720x576 output, compatible with PAL standard
400
-; '''-submenus'''
401
-: Create a sub-menu with chapters for each video (default: no sub-menus)
402
-; '''-ani-submenus'''
403
-: Create an animated sub-menu with chapters for each video (default: not
404
-: animated)
405
-; '''-no-menu | -nomenu'''
406
-: With this option todisc will just create a DVD file system, ready for
407
-: burning, with NO MENU, just the supplied video files.  These do not need
408
-: to be compliant, as non-compliant files will be encoded as usual.  The
409
-: '''-out''' option is not required.  Each  video will be a chapter unless
410
-: '''-chapters''' OPTION is passed.  The  '''-chapters''' option is a number
411
-: indicating the chapter interval in minutes, or a HH:MM:SS string
412
-: indicating chapter points.  See '''-chapters'''
413
-; '''-encode-only'''
414
-: This option was originally meant for the GUI, to allow it to be used for
415
-: just encoding rather than making a DVD structure.  But it works well from
416
-: the command line as well as it has the added advantage that you can input
417
-: a list of files.  Remember any makempg ('tovid mpg') options you use will
418
-: be passed on to the makempg script when encoding.
419
-
420
-=== Menu style ===
421
-
422
-; '''-showcase''' IMAGE|VIDEO
423
-: If used without an argument, use showcase style without a central thumb.
424
-: This is a different arrangement of images for the menu: small thumbnails
425
-: go at left (and right) side of screen, with a larger image in the centre.
426
-: Maximum of 10 videos.  If the provided argument is a video file, the
427
-: central thumb will be animated (regardless of whether '''-static''' is part
428
-: of the command line). Only 4:3 or 16:9 videos and images are accepted for
429
-: for the showcase file: if not one of these todisc will assume it is the
430
-: aspect ratio as the videos in the titleset.
431
-; '''-textmenu''', '''-text-menu''' NUM
432
-: If used without an argument, create a textmenu out of the supplied titles
433
-: The optional argument specifies how many titles are in the 1st column,
434
-: i.e. giving 4 titles and using "-textmenu 2" would make 2 columns of 2
435
-: titles. The default is to put all titles up to 13 in the first column
436
-: before starting a second column.  Maximum: 2 columns and 26 titles.
437
-: Note that column 2 titles are justified to the left unless you add
438
-: '''-edge-justify''' to the command line. The menu will be static if no video
439
-: files are supplied with either '''-background''' or '''-showcase''' options.
440
-; '''-quick-menu'''
441
-: If you are using ffmpeg 0.8 or newer you can use this option.  This will
442
-: make a very quick  menu by using ffmpeg instead of imagemagick.
443
-: There are two choices: you can either use '-showcase IMAGE|VIDEO' or
444
-: '-background VIDEO'.  There are no fancy effects like '''-wave'''
445
-: or '''-rotate''' available for it, but it is extremely fast.  It will be a
446
-: text-menu style of menu, with no video thumbs, and a central showcase
447
-: IMAGE(static) | VIDEO(animated).
448
-: (i) see '''-bg-color''' if you are not using a '''-background''' and want to
449
-: change the default.  (default is dark blue for -quick-menu arrangements). )
450
-: (ii) Note: todisc will still work with 'vhooks' if you have an old ffmpeg
451
-: with vhooks compiled in.
452
-: 
453
-: Specifying the IMAGE|VIDEO argument to '''-showcase''' is mandatory for this
454
-: style of menu, unless used in conjunction with '''-switched-menus'''
455
-: in which case the videos passed with '''-files''' automatically become the
456
-: showcase videos.  If '''-quick-menu''' is used in combination with
457
-: '''-switched-menus''' it really speeds up an otherwise time consuming process.
458
-: 
459
-: Example:
460
-<pre>
461
-    -quick-menu -showcase /home/grepper/showcase.mpg
462
-</pre>
463
-
464
-: See '''-switched-menus''' for example of making switched menus with
465
-: '''-quick-menu'''
466
-: 
467
-; '''-bg-color''', '''-bg-colour'''
468
-: The color to use for the menu background. (default: ntsc-safe black)
469
-: Note: use a color a great deal darker than you want, as it appears quite
470
-: a bit lighter in the video version.  You can use hexadecimal ('#ffac5f')
471
-: notation or named colors ('Lime').  convert -list color will show them.
472
-: See [http://www.imagemagick.org/script/color.php colors] for more details.
473
-; '''-submenu-bg-color''', '''-submenu-bg-colour'''
474
-: The color to use as background for the  submenu(s).
475
-: (default: ntsc-safe black)  See '''-bg-color'''
476
-; '''-static'''
477
-: Main menu will consist of static thumbnail links. (default: animated)
478
-: If you use a video for -showcase or -background then it will still be
479
-: a 'moving' menu, in spite of the static buttons.  This option also does
480
-: double duty for the '''-switched-menus''' option, and will create static
481
-: "switched" images.
482
-: See also '''-switched-menus'''
483
-; '''-background''' IMAGE|VIDEO
484
-: Menu background.  This can be a image file or an video file.  If it is a
485
-: video file the background will be animated.  Pick a file of correct aspect
486
-: ratio: i.e. it should still look good when resized to 4:3 aspect ratio.
487
-: It will be resized to fill the entire background.
488
-; '''-submenu-background''' IMAGE
489
-: Submenu background.  This can be only be an image file.  Pick a file of
490
-: correct aspect ratio: i.e. it should still look good when resized to
491
-: 4:3 aspect ratio.  It will be resized to fill the entire background.
492
-; '''-menu-title'''
493
-: Title for the root menu - may be longer than thumbnail labels
494
-: Also if you use \n in the title, you can use multi line titles, but you
495
-: would need to adjust '''-title-fontsize''' to something smaller than default
496
-: for example:
497
-: 
498
-<pre>
499
-    $ tovid disc ... -menu-title "A\nMultilined\nTitle" -title-fontsize 24
500
-</pre>
501
-
502
-; '''-title-font''', '''-menu-font''' FONT
503
-: Font to use for titles, either by ImageMagick font name (ex., "Arial") or
504
-: explicit pathname (ex., "/full/path/to/arial.ttf"). To see a complete
505
-: list of acceptable ImageMagick font names, run '''convert -list type''', and
506
-: refer to the leftmost column
507
-; '''-title-fontsize''', '''-menu-fontsize'''
508
-: Font size for main menu - best to -preview if you use this
509
-; '''-submenu-font'''
510
-: Font to use for the sub-menu main titles.  See '''-title-font'''
511
-; '''-submenu-fontsize'''
512
-: Font size for the sub-menu main titles
513
-; '''-menu-fade''' ['BACKGROUND DURATION']
514
-: Fade the menu in and out The background will fade in first, then title (and
515
-: mist if called for), then the menu thumbs.  The fadeout is in reverse
516
-: order.  'BACKGROUND DURATION' is an integer denoting the amount of time
517
-: the background will play before the menu begins to fade in.  This can allow
518
-: you to do a 'transition' to the menu: if you supply a -background VIDEO it
519
-: will play for the indicated time before the menu fades in.  Leave the
520
-: optional argument empty (just '''-menu-fade''') to get the default behavior
521
-: of showing the background for 1 second before fading the menu in.  To
522
-: disable the fadeout portion, use ''''-loop''' inf'.  See also:
523
-: '''-transition-to-menu''' and '''-loop'''
524
-; '''-transition-to-menu'''
525
-: This option goes with the '''-menu-fade''' option above, which must be
526
-: enabled for it to have effect.  It is a convenience option for animated
527
-: backgrounds: the background will become static at the exact point the
528
-: thumbs finish fading in. This menu does not loop unless you pass
529
-: '''-loop''' VALUE.  See also: '''-loop'''
530
-; '''-bgaudio''', '''-bg-audio*''' FILE
531
-: An file containing audio for the main menu background.  For static menus
532
-: the default is to use 20 seconds of audio.  You can change this using the
533
-: '''-menu-length''' option.
534
-; '''-submenu-audio''' FILE(S)
535
-: List of files for sub-menu audio backgrounds. If one file is given, then
536
-: it will be used for all sub-menus.  Otherwise the number given must equal
537
-: the number of submenus, though the keyword "none" in this list may be used for
538
-: silence.  See also '''-submenu-length'''
539
-; '''-titleset''' . . . '''-end-titleset'''
540
-: If you have more than one titleset, put options for each titleset between
541
-: '''-titleset''' and '''-end-titleset'''.  A separate menu will be created that
542
-: can be accessed from the main menu (VMGM).  You can create this main menu
543
-: using the '''-vmgm''' '''-end-vmgm''' options.  See '''-vmgm''' below and
544
-: TITLESET paragraph opening '''Usage''' section.
545
-; '''-vmgm''' . . . '''-end-vmgm'''
546
-: The VMGM menu is the root menu when you use titlesets.
547
-: Put your VMGM menu options between '''-vmgm''' and '''-end-vmgm'''.
548
-: You only need '''-titles''' "Titleset One title"  "Titleset Two title"
549
-: . . . , and not '''-files'''.
550
-: Any other options can be used, but the  menu will be a textmenu style by
551
-: default.  '''Hint''': use '''-showcase''' IMAGE/VIDEO to create a fancier
552
-: VMGM menu.
553
-; '''-no-vmgm-menu''', '''-no-vmgm'''
554
-: This will skip the creation of a VMGM ( root menu ) for titlesets. The DVD
555
-: will start with the first titleset.  You can not use this option unless also
556
-: using '''-quick-nav''' as you would not have a way to get to other titlesets.
557
-; '''-skip-vmgm'''
558
-: Start DVD from the first titleset instead of the VMGM ( root ) menu.
559
-; '''-switched-menus''', '''-switched-menu'''
560
-: This will make a "switched menu": there will be a central image where the
561
-: showcase image would go, and text menu titles along the menu edge where
562
-: textmenu titles go.  As you select a video title with the down or up arrow
563
-: on your DVD remote, the image in the centre will change to the image or
564
-: video made from that selected video. Do not use '''-showcase''' IMAGE/VIDEO
565
-: with this option.
566
-: 
567
-: This can be a time consuming process for making animated menus as you need
568
-: to make a separate menu for each video provided with '''-files'''.  The
569
-: process can be greatly sped up by using '''-quick-menu''' in conjunction with
570
-: this, though you will lose fancy options like '''-rotate''' and '''-wave'''.
571
-: 
572
-: Note that if you want to just have a static rather than an 'animated'
573
-: image, add '''-static''' to the command line.
574
-: 
575
-: Example for using with '''-quick-menu''':
576
-<pre>
577
-    -switched-menus -quick-menu
578
-</pre>
579
-
580
-
581
-=== Thumbnail style ===
582
-
583
-; '''-titles-font''' FONT
584
-: Display thumbnail or textmenu titles in the given font
585
-; '''-titles-fontsize''' POINTS
586
-: Font size to use for thumbnail or textmenu titles
587
-; '''-thumb-shape'''
588
-: normal|oval|vignette|plectrum|arch|spiral|blob|star|flare
589
-: Apply a shaped transparency mask to thumbnail videos.
590
-: These "feathered" shapes look best against a plain background (or used
591
-: in conjunction with '''-thumb-mist''' [COLOR]).  For this rectangular
592
-: semi-transparent misted background for each thumb:  see '''-thumb-mist'''.
593
-: Note: if you wish to make your own mask PNGS you can put them in
594
-: $PREFIX/lib/tovid/masks/ or $HOME/.tovid/masks/ and use them on the
595
-: command line using the filename minus the path and extension.
596
-: (i.e ~/.tovid/masks/tux.png becomes -thumb-shape tux)
597
-: No frame is used for shaped thumbs.
598
-; '''-thumb-frame-size''' INT
599
-: The size (thickness) of the thumb frames in pixels.  This will also set the
600
-: thickness of the raised "frame" of thumbs when you use '''-3d-thumbs'''.
601
-: See also '''-showcase-frame-size''' and '''-thumb-frame-color'''
602
-; '''-thumb-frame-color''', '''-thumb-frame-colour''' COLOR
603
-: The color of frames for video thumbnails.  Use hexadecimal or named colors
604
-: notation.  Remember to quote if using hexadecimal! ( '#ffac5f' ).
605
-; '''-3d-thumbs''', '''-3dthumbs'''
606
-: This will give an illusion of 3D to the thumbnails: dynamic lighting on
607
-: rounded thumbs, and a raised effect on rectangular thumbs.  Try it !
608
-
609
-=== Slideshows ===
610
-
611
-; '''-slides''' IMAGES
612
-: Use '''-slides''' IMAGES to pass in images for a slideshow.  The default is
613
-: to make an animated menu of the slides, moving from one slide to the
614
-: next. If you use '''-static''', a 'polaroid stack' montage is created.  This
615
-: composites the slides onto the background in 'random' locations with random
616
-: rotations.  '''-slides'''  IMAGES can be used multiple times if you wish to
617
-: make a menu with multiple slideshows.  You can also make a menu
618
-: of mixed videos and slideshows by using '''-slides''' IMAGES, and '''-files'''
619
-: VIDEOS multiple times.  For such a menu, the number of '''-titles'''
620
-: needs to match the number of '''-files''' passed in plus the number of
621
-: slideshows.  (Each time you use '''-slides''' counts as one title.)  To use
622
-: a transition between the slides, use '''-slide-transition'''
623
-: crossfade|fade.  See '''-slide-transition''' '''-menu-slide-total'''
624
-: 
625
-; '''-menu-slide-total''' INT
626
-: Use INT number of the slides that were passed in with '''-slides'''
627
-: to make the animated or static slide menu.  The length of the menu is
628
-: determined by 1) '''-menu-length''' NUM if given,  and by 2) the length
629
-: of the audio from '''-bgaudio'''.  For submenu slideshows, it is determined
630
-: by 1) '''-submenu-length''' NUM if given,  and by 2) the length of the
631
-: audio from '''-submenu-audio''' FILE(S).
632
-: 
633
-; '''-submenu-slide-total''' INT
634
-: This option is the same as '''-menu-slide-total''' except that it is
635
-: for submenu slideshows.
636
-: 
637
-; '''-slide-transition''' crossfade|fade [crossfade]
638
-: The type of fade transition between slides in a animated slide menu.  Be
639
-: sure the menu length is long enough to support the 1 second transitions
640
-: between the slides.  The length is determined by 1) the length of the
641
-: -bgaudio AUDIO  2) the length given with -menu-length NUM.  For submenu
642
-: slideshows, it is determined by 1) '''-submenu-length''' NUM if given,  and
643
-: by 2) the length of the audio from '''-submenu-audio''' FILE(S).
644
-: 
645
-: See '''-menu-slide-total''' , '''-bgaudio''' , '''-menu-length''' ,
646
-: '''-submenu-length''', and '''-submenu-audio'''.
647
-: 
648
-: The 'crossfade' transition fades from one slide to another.  The 'fade'
649
-: transition fades in and out from and to black.  If you don't use this
650
-: option, the default is to use a 'crossfade' transition.
651
-: 
652
-; '''-slideshow-menu-thumbs''' FILES
653
-: Use the FILES instead of the 1st image in each slideshow as the
654
-: thumb that shows on the menu.  This option is for multiple slideshows
655
-: or mixed slideshow/video menus only.
656
-: 
657
-; '''-slides-to-bin''' FILES
658
-: FILES will be resized to 640x480 using a 'box' filter - this
659
-: is called 'binning'.  It will reduce the 'signal to noise' ratio for the
660
-: image in the animated slide menu.  Use this if you get some unwanted
661
-: effects for certain images, such as pixels shifting in what should be a
662
-: static image.  See also '''-slides-to-blur''' and '''-slide-border'''
663
-: 
664
-; '''-slides-to-blur''' FILES
665
-: FILES will be blurred a small amount - which will help on
666
-: slides that still have noise even after 'binning' with -slides-to-bin.
667
-: The default blur is 0x0.2 - you can increase this with
668
-: -slide-blur ARG.  See also '''-slides-to-bin''' and '''-slide-border'''
669
-: 
670
-; '''-slide-blur''' VALUE or LIST of VALUES [0x0.2]
671
-: The argument to use for blurring files.  It will be passed to
672
-: imagemagick: convert -blur ARG.  The format of the arg is {radius}x{sigma}
673
-: and the default is 0x0.2. Using values between 0x0.1 and 0x0.9 is probably
674
-: the best range.  Use a single value for all, or a list to have a different
675
-: blur for each file passed with '''-slides-to-blur'''.  You must pass in
676
-: '''-files-to-blur''' FILES to use this option.  Blurring can help 'noise'
677
-: problems in the video.  See also '''-slides-to-bin''' and '''-slide-border'''
678
-: 
679
-; '''-slide-border''' WIDTH [100]
680
-: Pad the slides with a border for the animated slide menu.  The default
681
-: without using an argument is 100.  Using this option can also solve some
682
-: noise/ringing effects if used alone or in conjunction with 'binning'
683
-: ('''-slides-to-bin''') or blurring ('''-slides-to-blur''').
684
-: 
685
-; '''-slide-frame''' WIDTH [12]
686
-: Frame the slides for the animated slideshow menu.  The default width
687
-: without using an  argument is 12.  See also '''-slide-frame-color'''
688
-: 
689
-; '''-slide-frame-color''', '''-slide-frame-colour'''
690
-: The color of the slide frame if passing '''-slide-frame'''.  The default if
691
-: you don't use this option is a color-safe white: rgb(235,235,235).
692
-: 
693
-; '''-showcase-slideshow'''
694
-: If doing multiple slideshows or mixed videos and slideshow(s), then use
695
-: the animated slideshow as a showcase video.  It will be composed of slides
696
-: from each slideshow in the menu.  The thumb for each slideshow button will
697
-: be static.  If you used with a mixed menu of videos and slideshows, then
698
-: the video thumbs WILL be animated, so you may wish to use -static or
699
-: -textmenu with the option in that case.  If you want to use the
700
-: **-switched-menus option with a mixed menu leave this option out.
701
-: 
702
-; '''-background-slideshow''', '''-bg-slideshow'''
703
-: If doing multiple slideshows or mixed videos and slideshow(s), then use
704
-: the animated slideshow as a background video.  See '''-showcase-slideshow'''
705
-: for additional details.
706
-: 
707
-; '''-no-confirm-backup'''
708
-: Slideshows are an experimental (but well tested) feature.  Todisc is
709
-: unlikely to overwrite your personal files, but you should take precautions
710
-: and backup your images, as you would with any beta software.  Todisc
711
-: will prompt you to backup your files normally.  If you have already backed
712
-: up your images, use this option to disable the prompt.
713
-: See '''General Options'''
714
-: 
715
-; '''-use-dvd-slideshow''' [FILE CONFIG]
716
-: If you pass this option without an argument, tovid will use the
717
-: dvd-slideshow program to create the animated slide menu, assuming you have
718
-: this program installed.  The optional argument is the dvd-slideshow
719
-: configuration file  - if you don't use this argument tovid will create it
720
-: for you.  If you want to use the 'Ken Burns effect' - then the
721
-: configuration file argument is required.  Note: the configuration file will
722
-: override many of the above options for slideshows.
723
-
724
-=== Burning the disc ===
725
-
726
-; '''-burn'''
727
-: Prompt to burn the DVD directory on completion.
728
-: 
729
-; '''-device'''
730
-: Device to use for the burning program [ /dev/dvdrw ]
731
-: 
732
-; '''-speed'''
733
-: The speed to use for burning the disc.
734
-
735
-=== Advanced usage ===
736
-
737
-==== Options ====
738
-
739
-; '''-menu-length'''
740
-: The desired animated main menu length in seconds
741
-; '''-submenu-length'''
742
-: The desired submenu length.  This will also affect the length of submenu
743
-: audio for static submenus.  (Assuming that -submenu-audio was passed in).
744
-: The default is to use 10 seconds of audio for static menus.
745
-; '''-submenu-stroke''' COLOR
746
-: The color for the sub-menu font shadow
747
-; '''-submenu-title-color''', '''-submenu-title-colour'''
748
-: The fill color used for sub-menu title fonts
749
-; '''-submenu-titles'''
750
-: You can supply a list of titles here for sub-menus without the length
751
-: restrictions found in thumb titles.  Must equal number of videos
752
-; '''-chapters''' [ NUM | CHAPTER POINTS in HH:MM:SS ]
753
-: The number of chapters for each video (default: 6) OR
754
-: the actual chapter points in HH:MM:SS format.
755
-: Chapter points will be used for generating the submenu thumbs, and for
756
-: seeking with your DVD player.  You can pass in just one value that will
757
-: be used for all videos, or supply a list of values (number of chapters)
758
-: or time code strings.
759
-: 
760
-: If you just pass an integer for 'number of chapters', then tovid will
761
-: make the chapter points for you by dividing the video length by the number
762
-: you supply.  If using the '''-no-menu''' option, the INT passed in will be
763
-: the chapter interval in minutes, rather than the above formula.
764
-: 
765
-: If passing HH:MM:SS format you need to pass the string of chapter points for
766
-: each video and each string should have comma separated values.
767
-: Additionally, the first chapter should always start at 00:00:00 as
768
-: dvdauthor will add that if it is not there already.
769
-: 
770
-: To get your time codes, you can play your videos in mplayer and press 'o'
771
-: to see them on-screen.  I have found these to be very accurate in my short
772
-: tests.  For greater frame accuracy you could try loading the file in
773
-: avidemux and find the time codes for the frames you want.
774
-: 
775
-: If passing grouped chapters you need to join the chapters from all the
776
-: videos in a group with a '+' separator.  If you want to skip creating
777
-: chapters for a video in the group use '0' for its chapters.
778
-: 
779
-: Note: chapters for grouped videos should probably be passed in using the
780
-: above HH:MM:SS format. (Arbitrary chapters using just an INT for the # of
781
-: chapters is not guaranteed to work reliably in all cases for grouped videos
782
-: at the moment.)
783
-: 
784
-: Example for passing just number of chapters ( 4 videos ):
785
-<pre>
786
-    -chapters 5 2 4 8
787
-</pre>
788
-
789
-: 
790
-: Example of passing chapter points ( 4 videos ):
791
-<pre>
792
-    -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45 \
793
-    00:00:00,00:04:25.623,00:09:12,00:15:51 \
794
-    00:00:00,00:05:10,00:13:41,00:18:13.033 \
795
-    00:00:00,00:15:23.342,00:26:42.523
796
-</pre>
797
-
798
-: 
799
-: Example of passing grouped chapters using the '+' separator:
800
-<pre>
801
-    -chapters 00:00:00,00:05:34.41,00:12:54,00:20:45+00:04:23,00:09:35 \
802
-    00:00:00... etc.
803
-</pre>
804
-
805
-: 
806
-; '''-chapter-titles''' LIST
807
-: If you are using submenus, you can pass a list of titles for the
808
-: chapters.  Each title must be quoted, and the number of titles given
809
-: must equal the total number of chapters for all videos.  In other words
810
-: if you use -chapters 4 6 8 , you must give 18 chapter titles, in the same
811
-: order that the videos were passed in.  Note: if you are passing in options
812
-: on the command line to the 'tovid disc' GUI, you must repeat the option
813
-: '''-chapter-titles''' for each video, accompanied by its respective chapter
814
-: titles. (you can also choose to use this syntax for the todisc script.)
815
-: 
816
-; '''-chapter-font''' FONT
817
-: Use FONT as the font for submenu chapters.
818
-: 
819
-; '''-chapter-fontsize''' SIZE
820
-: Use SIZE as the pointsize for the chapters font.
821
-; '''-chapter-color''' COLOR
822
-: The color for the chapters font.
823
-; '''-chapter-stroke''' COLOR
824
-: The color for the chapters font shadow
825
-: 
826
-; '''-seek''' NUM | "NUM1 NUM2 NUM3 . . ."
827
-: Seek to NUM seconds before generating thumbnails (default: 2.0 seconds)
828
-: If a quoted string of values matching the number of videos is used, then
829
-: each video can use a different seek value
830
-: If using switched menus, the '''-seek''' value(s) will be used to generate
831
-: the showcase image that displays on switching to another video choice with
832
-: the up/down arrow keys.
833
-; '''-fast-seek'''
834
-: Use faster seek method for ffmpeg.  This is not as accurate as the default
835
-: method, and may produce grey frames.
836
-; '''-frame-safe'''  Instead of seeking and then outputting one frame for
837
-: previews and static menus, output 9 frames and choose the largest.  Not
838
-: frame accurate (may be as much as 9 frames off), but safer.  Choose this
839
-: if you are getting grey frames/thumbnails with some videos.  You can also
840
-: use it to try to get the 'best' frame.  This option
841
-: has no effect on submenus at present.
842
-; '''-showcase-seek''' NUM
843
-: Seek to NUM seconds before generating thumbnails for showcase video
844
-: (default: 2.0 seconds)
845
-; '''-bgvideo-seek''', '''-bg-video-seek''' NUM
846
-: Seek to NUM seconds before generating images for background video
847
-: (default: 2.0 seconds)
848
-; '''-bgaudio-seek''', **-bg-audio-seek NUM
849
-: Seek to NUM seconds before generating audio for bgaudio
850
-: (default: 2.0 seconds)
851
-; '''-group''' N VIDEO1 VIDEO2 . . .
852
-: Allow grouping videos in dvdauthor.xml, so they will play sequentially as
853
-: a group.  The videos passed in after the 'N' will be grouped with the 'Nth'
854
-: video. Example:
855
-: 
856
-<pre>
857
-    -group 2 2.mpg 3.mpg 4.mpg
858
-</pre>
859
-
860
-: 
861
-: will group these 3 videos with the 2nd video given with '''-files''', so that
862
-: they will play sequentially as one title.  Only one thumbnail and/or title
863
-: will appear on the menu for the group: it will be made from the 1st video
864
-: in the group.  In the above example if you passed:
865
-<pre>
866
-    -files foo.mpg bar.mpg baz.mpg -group 2 2.mpg 3.mpg 4.mpg
867
-</pre>
868
-
869
-: then the group will consist of bar.mpg  2.mpg, 3.mpg and 4.mpg, and only the
870
-: title and/or thumbnail for bar.mpg will appear in the menu.  You can use
871
-: '''-group''' more than once for multiple groups.  Be  sure to quote video
872
-: filenames if they contain  spaces.
873
-
874
-=== Menu Style ===
875
-
876
-; '''-menu-title-geo''' north|south|east|west|center [south]
877
-: The position of the menu title.  You may need to use -align as well if
878
-: you don't want your title covering other parts of your menu.  See
879
-: '''-align'''
880
-; '''-menu-title-offset''' OFFSET (+X+Y)
881
-: Move menu title by this offset from its N|S|E|W|Center position.  You
882
-: may need to use -align as well if you don't want your title covering other
883
-: parts of your menu.  See '''-align'''
884
-; '''-button-style''' line|rect|text|text-rect [line]
885
-: The style of button that you will see when you play the DVD.
886
-: "line" style underlines the title, "rect" draws a rectangle around the
887
-: thumb when you select it in the DVD player, "text" highlights the video
888
-: title text, and "text-rect" draws a rectangle around the title
889
-: text.
890
-; '''-title-color''', '''-title-colour''' COLOR
891
-: Color to use for the main menu title.  For list of supported colors do:
892
-: '''convert -list''' color.  HTML notation may be used: "#ff0000". See:
893
-: [http://www.imagemagick.org/script/color.php]
894
-; '''-title-stroke''' COLOR
895
-: Shadow color for the main menu's title font. Use "none" for transparent
896
-: outline  (see title-color).  Note: this is not a -stroke in the sense that
897
-: imagemagick uses the term, but a shadow (the font is drawn twice).  To get
898
-: a true imagemagick stroke see '''-title-font-deco'''
899
-; '''-title-font-deco''', '''-title-fontdeco''' "IMAGEMAGICK STRING"
900
-: Sets the font decoration method to FONTDECORATION. It is used by the 'convert'
901
-: ImageMagick command to draw the menu text. You can add colored text
902
-: outlines, gradient fills, and many others. See '''Usage notes'''
903
-; '''-titles-stroke''' COLOR
904
-: Shadow color for the thumb or textmenu video titles font. Use "none" for
905
-: transparent outline  (see '''-titles-color''').  Note: this is not a -stroke
906
-: in the sense that imagemagick uses the term, but a shadow
907
-: (the font is drawn twice).  To get a true imagemagick stroke,
908
-: see '''-titles-font-deco'''
909
-; '''-titles-font-deco''', '''-titles-fontdeco''' "IMAGEMAGICK STRING"
910
-: Sets the font decoration method to FONTDECORATION. It is used by the 'convert'
911
-: ImageMagick command to draw the menu text. You can add colored text
912
-: outlines, gradient fills, and others. See '''Usage notes''' for more info.
913
-; '''-highlight-color''', '''-highlight-colour'''
914
-: Color to use for the menu buttons that your DVD remote uses to navigate.
915
-; '''-select-color''', '''-select-colour'''
916
-: Color to use for the menu buttons that your DVD remote uses to select.
917
-; '''-text-mist'''
918
-: Put a semi-transparent misted background behind the text for the menu's
919
-: title, just slightly larger than the text area.
920
-; '''-text-mist-color''', '''-text-mist-colour''' COLOR
921
-: Color of the mist behind the menu's title (see title-color).
922
-; '''-text-mist-opacity'''
923
-: Opacity of the mist behind the menu's title - see '''-opacity'''
924
-; '''-title-opacity'''
925
-: Opacity of the menu title text
926
-; '''-titles-opacity'''
927
-: Opacity of the text for video titles
928
-; '''-submenu-title-opacity'''
929
-: Opacity of the text for submenu menu titles
930
-; '''-chapter-title-opacity'''
931
-: Opacity of the text for submenu chapter titles
932
-; '''-menu-audio-fade'''
933
-: Number of sec to fade given menu audio in and out (default: 1.0 seconds)
934
-: If you use '''-menu-audio-fade''' 0 then the audio will not be faded.
935
-; '''-submenu-audio-fade'''
936
-: Number of secs to fade sub-menu audio in and out (default: 1.0 seconds).
937
-: See '''-menu-audio-fade'''
938
-; '''-intro''' VIDEO
939
-: Use a introductory video that will play before the main menu.
940
-: At present it must be a DVD compatible video at the correct resolution etc.
941
-: Only 4:3 aspect is supported: 16:9 will give unexpected results.
942
-
943
-==== Style options specific to showcase/textmenu arrangements ====
944
-
945
-; '''-text-start''' N
946
-: This option is for '''-textmenu''' menus.  The titles will start at the Nth
947
-: pixel from the top of the menu ( Y axis ).
948
-; '''-title-gap''' N
949
-: This option is for '''-textmenu''' menus.  The gap is the space between
950
-: titles vertically ( Y axis ).
951
-; '''-rotate''' DEGREES
952
-: Rotate the showcase image|video clockwise by DEGREES.
953
-: (default: if used without options, the rotate will be 5 degrees).  Note:
954
-: this will not turn a portait image into a landscape image!
955
-; '''-showcase-geo''' GEOMETRY
956
-: The position of the showcase image.  ( +X+Y  position )
957
-: For example: '''-showcase-geo''' +300+200
958
-; '''-wave''' default|GEOMETRY
959
-: Wave effect for showcase image|video.  Alters thumbs along a sine wave using
960
-: GEOMETRY. (default: no wave)
961
-: "default" will produce a wave arg of -20x556, which
962
-: produces a gentle wave with a small amount of distortion.
963
-: See: [http://www.imagemagick.org/Usage/distorts/#wave] if you want
964
-: to try other values.
965
-; '''-showcase-shape'''  egg|oval|plectrum|arch|spiral|galaxy|flat-tube|normal
966
-: Apply a shaped transparency mask to showcase videos or images.
967
-: Note: if you wish to make your own mask PNGS you can put them in
968
-: $PREFIX/lib/tovid/masks/ or $HOME/.tovid/masks/ and use them on the
969
-: command line using the filename minus the path and extension.
970
-: No frame is used for shaped thumbs.
971
-; '''-showcase-framestyle'''  none|glass
972
-: For -showcase-* style template only
973
-: "none" will use the default frame method, using "convert -frame . . ."
974
-: "glass" will use mplayer to make frames, which gives an interesting
975
-: animated effect to the frames, and can be much faster ( especially if you
976
-: don't use '''-rotate''' or '''-wave''' as thumbs will not need to be processed
977
-: again after mplayer spits them out.  Note: you need to be using either
978
-: '''-showcase''' IMAGE or '''-showcase''' VIDEO for this "frame style" to work.
979
-; '''-showcase-frame-size''' PIXELS
980
-: The size of the showcase frame.  This value will be used for both width and
981
-: height for the 'thickness' of the frame.  This will also set the thickness
982
-: of the raised "frame" of the showcase thumb when you use '''-3d-showcase'''.
983
-: See also '''-thumb-frame-size''' and '''-showcase-frame-color'''
984
-; '''-showcase-frame-color''', '''-showcase-frame-colour''' PIXELS
985
-: The color of the showcase frame.  Use hexadecimal or named colors notation.
986
-: Remember to quote! ( '#ffac5f' ).
987
-; '''-3d-showcase''', '''-3dshowcase'''
988
-: This will give an illusion of 3D to the showcase thumb: dynamic lighting on
989
-: rounded thumbs, and a raised effect on rectangular thumbs.  Try it !
990
-
991
-=== Thumbnail Style ===
992
-
993
-; '''-user-thumbs''' IMAGE(S)
994
-: Supply your own images for menu buttons, rather than relying on todisc to
995
-: generate them from the video.  They must be the same aspect ratio as the
996
-: videos in the titleset (4:3 or 16:9), as todisc will resize them without
997
-: checking and cropping.  There must be on image for each thumb that will be
998
-: displayed on the menu (ie. one thumb for each video in a titleset).
999
-; '''-opacity''' [0-100] (default 100)
1000
-: Opacity of thumbnail videos as a percentage (no percent sign).
1001
-: Anything less than 100(%) is semi-transparent. Not recommended with dark
1002
-: backgrounds.
1003
-; '''-thumb-blur''', '''-blur''' NUM
1004
-: The amount of feather blur to apply to the thumb-shape.  The default is 1.0
1005
-: which will more or less keep the shape and produces transparency at the
1006
-: edges.  Choose float or integer values between 0.1 and 2.0. 3D thumbs are
1007
-: set to a tiny blur, so this option doesn't affect the '''-3dthumbs''' option.
1008
-; '''-showcase-blur''' NUM
1009
-: The amount of 'feather' blur to apply to the showcase image/video.  Choose
1010
-: values between 0.1 and 2.0.  This option has no effect on '''-3d-showcase'''.
1011
-: See '''-thumb-blur''' for more info.
1012
-; '''-align''' DIRECTION
1013
-: This will align  thumbs/titles in DIRECTION, which is a compass direction
1014
-: as used by imagemagick: ie. north|south|east|west|northeast|northwest etc.
1015
-: If '''-align''' south then menu title will align north, unless you manually
1016
-: set one or both of '''-menu-title-geo''' or '''-menu-title-offset'''.
1017
-: Only '''-align''' north|south|center has any effect on showcase with thumb,
1018
-: or with the default montage arrangement of central thumbs. The most
1019
-: apparent changes with be with textmenu, though with 2 column arrangements
1020
-: only the north* and south* changes will show an effect.
1021
-: 
1022
-: Diagram:
1023
-;    . northwest   north   northeast .
1024
-;    .                               .
1025
-;    . west        center       east .
1026
-;    .                               .
1027
-;    . southwest   south    souteast .
1028
-; '''-thumb-mist''' [COLOR]
1029
-: Use a mist behind thumbnails.  The optional argument is the color of the
1030
-: mist.  This option helps with contrast.  Be sure to set the font color
1031
-: to an appropriate color if using a colored mist, and/or use a bold font.
1032
-; '''-titles-color''', '''-titles-colour''' COLOR
1033
-: Color to use for the thumb or textmenu titles.  If your titles are not
1034
-: clear enough or look washed out, try using a '''-titles-stroke''' that
1035
-: is the same color as used with '''-titles-color'''  (see '''-title-color''')
1036
-; '''-showcase-titles-align''' west|east (default: center [centre])
1037
-: The default is to center the text above the thumbnails.  This option will
1038
-: align the titles either to the left (west) or right (east).  Aligning west
1039
-: gives more space to the titles.  Aligning east also does so, and as well
1040
-: will facilitate using \n in your titles to achieve multi line titles.
1041
-; '''-tile-3x1''', '''-tile3x1'''
1042
-: Use a montage tile of 3x1 instead of the usual 2x2 for 3 videos
1043
-: ie.
1044
-: 
1045
-: [movie1] [movie2] [movie3] instead of:
1046
-: 
1047
-: [movie1] [movie2]
1048
-: 
1049
-: [movie3]
1050
-: 
1051
-: This option only comes into play if the number of videos supplied equals 3
1052
-: Otherwise it will be silently ignored. Not used for -showcase-* style.
1053
-; '''-tile-4x1''', '''-tile4x1'''
1054
-: Same as '''-tile-3x1''' above, except use tile of 4x1. (one row of 4 videos)
1055
-; **-thumb-columns 3|4
1056
-: Same as '''-tile-3x1''' and tile-4x1** above, except it accepts either '3'
1057
-: (1 row of 3 thumbs), or '4' (one row of 4 thumbs) as an argument.  This
1058
-: alternative was added to help compact the gui layout.
1059
-; '''-rotate-thumbs''' DEGREE LIST ( list of degrees, one for each thumb )
1060
-: Rotate thumbs the given amount in degrees - can be positive or negative.
1061
-: There must be one value for each file given with '''-files'''.
1062
-: If the values are not the same distance from zero, the thumbs will be of
1063
-: different sizes as images are necessarily resized *after* rotating.  With
1064
-: the default montage template - this will also resize the titles; with the
1065
-: showcase template the titles will remain the same size. Example:
1066
-: 
1067
-<pre>
1068
-    -rotate-thumbs -10 10 -10 10 -10  (for 5 files)
1069
-</pre>
1070
-
1071
-: **Note: this option will not turn a portrait image into a landscape image!
1072
-
1073
-=== Dvdauthor options ===
1074
-
1075
-; '''-loop''' PAUSE
1076
-: Pause in seconds at end of menu.  Use "inf" if you wish indefinite pause.
1077
-: Note: using "inf" with '''-menu-fade''' will disable the fadeout portion of
1078
-: the fade.  (default: "inf" for static menu, 10.0 seconds for animated.)
1079
-; '''-playall'''
1080
-: This option will create a button on the main menu that will allow going
1081
-: right to the 1st title and playing all videos in succession before
1082
-: returning to the main menu.  If doing titlesets you can use this within
1083
-: the '''-vmgm''' ... '''-end-vmgm''' options to allow playing ALL titlesets.
1084
-: (If you want also to have a playall button in each titleset you could use
1085
-: this option between each '''-titleset''' ... '''-end-titleset''' option or put
1086
-: it outside of the vmgm and titlset options as a global option.
1087
-; '''-videos-are-chapters'''
1088
-: A button will be made on the main menu for each video, which you can use as
1089
-: a chapter button.  Selecting any video will play them all in order
1090
-: starting with the selected one.
1091
-; '''-chain-videos''' NUM | N1-NN
1092
-: Without options this will chain all videos together so they play
1093
-: sequentially without returning to the main menu, except for the last, which
1094
-: will return.  You can also specify which videos you want to behave this way
1095
-: by number or by a range. ( ie. '''-chain-videos''' 1 2 4-6 ).
1096
-; '''-subtitle-lang''' "lang1 lang2 . . ."
1097
-: This allows selectable subtitles in the DVD, assuming you have optional
1098
-: subtitles muxed into your videos.  Use 2 character language codes.
1099
-; '''-audio-channel''' "Video1_track Video2_track Video3_track . . ."
1100
-: "VideoN_track" is the track number to use in a multi-track (multi-language)
1101
-: mpeg: usually something like '''-audio-channel''' "1 0 1".  The 1st track is
1102
-: 0, 2nd is 1 . . . etc.  If the tracks are 0. English 1.French, then the
1103
-: above would make French the audio language on Video1 and Video3, and
1104
-: English the audio language on Video2.  You can check the mpeg with
1105
-: "mplayer -v . . .".
1106
-; '''-audio-lang''' LANGUAGE CODES
1107
-: Identify the audio tracks on the DVD.  These language codes are used for
1108
-: each video in the titleset.  When you use the audio button on your DVD
1109
-: remote the language name is displayed.  Example: '''-audio-lang''' en fr
1110
-; '''-aspect''' 4:3|16:9
1111
-: This will output a <video aspect WIDTH:HEIGHT /> tag for the dvdauthor
1112
-: xml file.  It will affect all videos in the titleset.  Example:
1113
-: 
1114
-<pre>
1115
-    -aspect 16:9
1116
-</pre>
1117
-
1118
-; '''-widescreen''' nopanscan|noletterbox [nopanscan]
1119
-: This will output a <video widescreen=nopanscan /> tag (for example)
1120
-: for the dvdauthor xml file.  It will affect all videos in the titleset. Use
1121
-: in conjunction with '''-aspect''' if your dvd player is cropping your videos.
1122
-: Example:
1123
-: 
1124
-<pre>
1125
-    -aspect 16:9 -widescreen
1126
-</pre>
1127
-
1128
-; '''-quick-nav'''
1129
-: This option will allow navigation of a menu with more than one titleset by
1130
-: using the left and right arrow keys of your DVD remote.  When you press
1131
-: this key the highlight will go the next or previous title.  If you are at
1132
-: the end of a titleset the right key will go to the next titleset.  If you
1133
-: are at the beginning of a titleset, the left key will go to the previous
1134
-: titleset.  If no next or previous titleset it will cycle to the end or
1135
-: beginning of the titlesets.
1136
-; '''-outlinewidth''', '''-outline-width''' WIDTH
1137
-: For spumux outlinewidth variable.  If there is a large gap between words in
1138
-: a text button, this option may help.
1139
-; '''-video-pause''' PAUSE (single value or list)
1140
-: The pause in seconds after playing a video title.  This is useful for
1141
-: slideshows: the 'slide' will remain on the screen for this length of time.
1142
-: If you have grouped videos you should probably not pause the videos that
1143
-: have a grouped title after it, but instead see '''-grouped-video-pause'''.
1144
-: Note: if you provide a list of values they must be one for each video.
1145
-; '''-group-video-pause''' PAUSE (single value or list)
1146
-: The pause in seconds after a grouped video plays.  If you wish to pause
1147
-: after the whole group finishes, then only use a value greater than zero
1148
-: for the last video in the group.  If providing a list of values they must
1149
-: equal the number of grouped videos.
1150
-
1151
-=== Usage notes ===
1152
-
1153
-The argument given to various *-font options that set the font to use must be
1154
-one of the fonts listed by the command 'convert -list type'. Please note that
1155
-many of your installed fonts may not be available; if you want to maximize the
1156
-number of fonts available to todisc, download and run
1157
-[http://www.cit.gu.edu.au/~anthony/anthony.html Anthony Thyssen's]
1158
-[http://www.imagemagick.org/Usage/scripts/imagick_type_gen imagick_type_gen]
1159
-script and run it like this:
1160
-imagick_type_gen > ~/.magick/type.xml.
1161
-If that doesn't work, try imagick_type_gen > ~/.magick/type.mgk.
1162
-
1163
-Or you can specify a ttf font file directly to the *-font options if you don't
1164
-want to install fonts to ImageMagick.
1165
-
1166
-The *-stroke options in todisc are not a stroke in the sense that ImageMagick
1167
-uses the term, but rather a font shadow (the text is drawn twice)  To get a
1168
-truer Imagemagick -stroke try something like:
1169
--title-font-deco "-stroke black" (or -titles-font-deco "-stroke black").  The
1170
-'''-fontdeco''' option is quite flexible and takes a lot of ImageMagick's
1171
-''convert'' options. Please refer to the tovid
1172
-[http://tovid.wikia.com/wiki/Making_a_DVD_with_text_menus wiki] and Anthony
1173
-Thyssen's guide [[http://www.imagemagick.org/Usage]] for further explanation and examples.
1174
-
1175
-== Command:mpg ==
1176
-
1177
-'''tovid mpg''' converts arbitrary video files into (S)VCD/DVD-compliant
1178
-MPEG format, suitable for burning to CD/DVD-R for playback on a
1179
-standalone DVD player.
1180
-
1181
-=== Usage ===
1182
-
1183
-'''tovid mpg''' [''OPTIONS''] '''-in''' ''INFILE'' '''-out''' ''OUTPREFIX''
1184
-
1185
-Where ''INFILE'' is any multimedia video file, and ''OUTPREFIX'' is what
1186
-you want to call the output file, minus the file extension. ''OPTIONS''
1187
-are additional customizations, described below.
1188
-
1189
-By default, you will (hopefully) end up with an NTSC DVD-compliant
1190
-MPEG-2 video file; if you burn this file to a DVD-R, it should be
1191
-playable on most DVD players.
1192
-
1193
-For example:
1194
-
1195
-; <tt>tovid mpg -in foo.avi -out foo_encoded</tt>
1196
-: Convert 'foo.avi' to NTSC DVD format, saving to 'foo_encoded.mpg'.
1197
-: 
1198
-; <tt>tovid mpg -pal -vcd foo.avi -out foo_encoded</tt>
1199
-: Convert 'foo.avi' to PAL VCD format, saving to 'foo_encoded.mpg'.
1200
-
1201
-=== Basic options ===
1202
-
1203
-; '''-v''', '''-version'''
1204
-: Print tovid version number only, then exit.
1205
-; '''-quiet'''
1206
-: Reduce output to the console.
1207
-; '''-fake'''
1208
-: Do not actually encode; only print the commands (mplayer, mpeg2enc etc.)
1209
-: that would be executed. Useful in debugging; have tovid give you the
1210
-: commands, and run them manually.
1211
-; '''-ffmpeg'''
1212
-: Use ffmpeg for video encoding, instead of mplayer/mpeg2enc. Try this if
1213
-: you have any problems with the default encoding method. Using this option,
1214
-: encoding will be considerably faster. It can do almost everything that 
1215
-: mpeg2enc does such as -filters and -subtitles by using a pipe from mplayer
1216
-: though using these options will make encoding somewhat slower. The 
1217
-: exceptions are some special options like -kvcd* -bdvd where you will still
1218
-: need to use the default mpeg2enc option.
1219
-
1220
-==== Television standards ====
1221
-
1222
-; '''-ntsc'''
1223
-: NTSC format video (USA, Americas) (default)
1224
-; '''-ntscfilm'''
1225
-: NTSC-film format video
1226
-; '''-pal'''
1227
-: PAL format video (Europe and others)
1228
-
1229
-==== Formats ====
1230
-
1231
-Standard formats, should be playable in most DVD players:
1232
-
1233
-; '''-dvd'''
1234
-: (720x480 NTSC, 720x576 PAL) DVD-compatible output (default)
1235
-; '''-half-dvd'''
1236
-: (352x480 NTSC, 352x576 PAL) Half-D1-compatible output
1237
-; '''-svcd'''
1238
-: (480x480 NTSC, 480x576 PAL) Super VideoCD-compatible output
1239
-; '''-dvd-vcd'''
1240
-: (352x240 NTSC, 352x288 PAL) VCD-on-DVD output
1241
-; '''-vcd'''
1242
-: (352x240 NTSC, 352x288 PAL) VideoCD-compatible output
1243
-
1244
-Non-standard formats, playable in some DVD players:
1245
-
1246
-; '''-kvcd'''
1247
-: (352x240 NTSC, 352x288 PAL) KVCD-enhanced long-playing video CD
1248
-; '''-kdvd'''
1249
-: (720x480 NTSC, 720x576 PAL) KVCD-enhanced long-playing DVD
1250
-; '''-kvcdx3'''
1251
-: (528x480 NTSC, 520x576 PAL) KVCDx3 specification
1252
-; '''-kvcdx3a'''
1253
-: (544x480 NTSC, 544x576 PAL) KVCDx3a specification (slightly wider)
1254
-; '''-bdvd'''
1255
-: (720x480 NTSC, 720x576 PAL) BVCD-enhanced long-playing DVD
1256
-
1257
-See [http://kvcd.net/ kvcd.net] for details on the KVCD specification. Please
1258
-note that KVCD ("K Video Compression Dynamics") is the name of a compression
1259
-scheme that can be applied to any MPEG-1 or MPEG-2 video, and has little to
1260
-do with VCD ("Video Compact Disc"), which is the name of a standard video disc
1261
-format.
1262
-
1263
-=== Advanced options ===
1264
-
1265
-==== Aspect ratios ====
1266
-
1267
-tovid automatically determines aspect ratio of the input video by playing it in
1268
-mplayer. If your video plays with correct aspect in mplayer, you should not
1269
-need to override the default tovid behavior.
1270
-
1271
-If mplayer does not play your video with correct aspect, you may provide an
1272
-explicit aspect ratio in one of several ways:
1273
-
1274
-; '''-full'''
1275
-: Same as '''-aspect 4:3'''
1276
-; '''-wide'''
1277
-: Same as '''-aspect 16:9'''
1278
-; '''-panavision'''
1279
-: Same as '''-aspect 235:100'''
1280
-; '''-aspect''' ''WIDTH''''':'''''HEIGHT''
1281
-: Custom aspect, where ''WIDTH'' and ''HEIGHT'' are integers.
1282
-
1283
-The above are the intended INPUT aspect ratio. tovid chooses an optimal output
1284
-aspect ratio for the selected disc format (VCD, DVD, etc.) and does the
1285
-appropriate letterboxing or anamorphic scaling. Use '''-widetv''' to encode
1286
-for a widescreen monitor or TV.
1287
-
1288
-==== Video stream options ====
1289
-
1290
-; '''-quality''' ''NUM'' (default 6)
1291
-: Desired output quality, on a scale of 1 to 10, with 10 giving the best
1292
-: quality at the expense of a larger output file. Default is 6. Output size
1293
-: can vary by approximately a factor of 4 (that is, '''-quality 1''' output
1294
-: can be 1/4 the size of '''-quality 10''' output). Your results may vary.
1295
-: WARNING: With '''-quality 10''', the output bitrate may be too high for
1296
-: your hardware DVD player to handle. Stick with 9 or lower unless you
1297
-: have phenomenally good eyesight.
1298
-: 
1299
-: At present, this option affects both output bitrate and quantization (but
1300
-: may, in the future, affect other quality/size-related attributes). Use
1301
-: '''-vbitrate''' if you want to explicitly provide a maximum bitrate.
1302
-: 
1303
-; '''-vbitrate''' ''NUM''
1304
-: Maximum bitrate to use for video (in kbits/sec). Must be within allowable
1305
-: limits for the given format. Overrides default values. Ignored for VCD,
1306
-: which must be constant bitrate.
1307
-: 
1308
-; '''-interlaced'''
1309
-: Do interlaced encoding of the input video (top fields first). Use this
1310
-: option if your video is  interlaced, and you want to preserve as much
1311
-: picture quality as possible. This option is ignored for VCD, which
1312
-: doesn't support it.
1313
-: 
1314
-: You can tell your source video is interlaced by playing it, and pausing
1315
-: during a scene with horizontal motion; if you see a "comb" effect at the
1316
-: edges of objects in the scene, you have interlaced video. Use this option
1317
-: to encode it properly.
1318
-: 
1319
-: If you would prefer to have output in progressive format, use
1320
-: '''-progressive'''. If you have a DV camera, use '''-interlaced_bf''' since
1321
-: DV footage is generally bottom fields first.
1322
-: 
1323
-; '''-interlaced_bf'''
1324
-: Do interlaced encoding of the input video (bottom fields first).
1325
-: 
1326
-; '''-deinterlace''', '''-progressive'''
1327
-: Convert interlaced source video into progressive output video. Because
1328
-: deinterlacing works by averaging fields together, some picture quality is
1329
-: invariably lost. Uses an adaptive kernel deinterlacer (kerndeint), or,
1330
-: if that's not available, the libavcodec deinterlacer (lavcdeint).
1331
-: 
1332
-; '''-mkvsub''' ''LANG'' (EXPERIMENTAL)
1333
-: Attempt to encode an integrated subtitle stream (such as may be found in
1334
-: Matroska .mkv files) in the given language code (eng, jpn, etc.) May work
1335
-: for other formats.
1336
-: 
1337
-; '''-autosubs'''
1338
-: Automatically include subtitle files with the same name as the input video.
1339
-: 
1340
-; '''-subtitles''' ''FILE''
1341
-: Get subtitles from ''FILE'' and encode them into the video.  WARNING: This
1342
-: hard-codes the subtitles into the video, and you cannot turn them off while
1343
-: viewing the video. By default, no subtitles are loaded. If your video is
1344
-: already compliant with the chosen output format, it will be re-encoded to
1345
-: include the subtitles. This works with both -ffmpeg and the default,
1346
-: mpeg2enc.
1347
-: 
1348
-; '''-dvd-subtitles''', '''-dvdsubs''' | ''FILE''
1349
-: Get subtitles from ''FILE(S)'' and add them '''as a subtitle stream''' into the
1350
-: video.  This allows selectable subtitles on your DVD. You can use more than
1351
-: one file for multiple languages. Be sure to use the -subtitle-lang option
1352
-: in 'tovid disc' so the name of the language will show up on the DVD instead
1353
-: of 'UNKNOWN' or similar
1354
-: 
1355
-; '''-dvdsubs-only'''
1356
-: Use this if you have an already complient MPEG and wish to add a subtitle
1357
-: stream without re-encoding, using '''-dvdsubs''' ,
1358
-: 
1359
-; '''-dvdsubs-fontsize''' ''NUM'' [18]
1360
-: The pointsize in pixels for DVD selectable subtitles. To affect this for
1361
-: hard-coded subtitles ( '''-subtitles''' ) you will need to pass options to
1362
-: the player via '''-mplayeropts''' or '''-mpvopts'''.
1363
-: 
1364
-; '''-type''' {live|animation|bw}
1365
-: Optimize video encoding for different kinds of video. Use 'live' (default)
1366
-: for live-action video, use 'animation' for cartoons or anime, and 'bw' for
1367
-: black-and-white video.  This option currently only has an effect with
1368
-: KVCD/KSVCD output formats; other formats may support this in the future.
1369
-: 
1370
-; '''-safe''' ''PERCENT''
1371
-: Fit the video within a safe area defined by ''PERCENT''. For example,
1372
-: '''-safe 90%''' will scale the video to 90% of the width/height of the output
1373
-: resolution, and pad the edges with a black border. Use this if some of the
1374
-: picture is cut off when played on your TV.  The percent sign is optional.
1375
-: 
1376
-; '''-filters''' {none,denoise,deblock,contrast,all} (default none)
1377
-: Apply post-processing filters to enhance the video. If your input video is
1378
-: very high quality, use 'none'. If your input video is grainy, use 'denoise';
1379
-: if it looks washed out or faded, use 'contrast'. You can use multiple
1380
-: filters separated by commas. To apply all filters, use 'all'. This works
1381
-: with both mpeg2enc and -ffmpeg.
1382
-: 
1383
-; '''-fps''' ''RATIO''
1384
-: Force input video to be interpreted as ''RATIO'' frames per second.  May be
1385
-: necessary for some ASF, MOV, or other videos. ''RATIO'' should be an
1386
-: integer ratio such as "24000:1001" (23.976fps), "30000:1001" (29.97fps), or
1387
-: "25:1" (25fps). This option is temporary, and may disappear in future
1388
-: releases. (Hint: To convert a decimal like 23.976 to an integer ratio, just
1389
-: multiply by 1000, i.e. 23976:1000)
1390
-: 
1391
-; '''-crop''' ''WIDTH'':''HEIGHT'':''X'':''Y''
1392
-: Crop a portion of the video ''WIDTH'' by ''HEIGHT'' in size, with the
1393
-: top-left corner at ''X'', ''Y''.
1394
-: 
1395
-; '''-widetv'''
1396
-: Always encode to 16:9 widescreen (only supported by '''-dvd''', '''-kdvd''',
1397
-: '''-bdvd'''), for optimal viewing on a widescreen monitor or TV.
1398
-
1399
-==== Audio stream options ====
1400
-
1401
-; '''-normalize'''
1402
-: Analyze the audio stream and then normalize the volume of the audio.
1403
-: This is useful if the audio is too quiet or too loud, or you want to
1404
-: make volume consistent for a bunch of videos. Similar to running
1405
-: normalize without any parameters. The default is -12dB average level
1406
-: with 0dB gain.
1407
-: 
1408
-; '''-amplitude''' ''NUM''[dB]
1409
-: In addition to analyzing and normalizing, apply the gain to the audio
1410
-: such that the 'average' (RMS) sound level is ''NUM''. Valid values
1411
-: range 0.0 - 1.0, with 0.0 being silent and 1.0 being full scale. Use
1412
-: ''NUM''dB for a decibel gain below full scale (the default without
1413
-: -amplitude is -12dB).
1414
-: 
1415
-; '''-abitrate''' ''NUM''
1416
-: Encode audio at ''NUM'' kilobits per second.  Reasonable values include
1417
-: 128, 224, and 384. The default is 224 kbits/sec, good enough for most
1418
-: encodings. The value must be within the allowable range for the chosen disc
1419
-: format; Ignored for VCD, which must be 224.
1420
-: 
1421
-; '''-audiotrack''' ''NUM''
1422
-: Encode the given audio track, if the input video has multiple audio tracks.
1423
-: ''NUM'' is ''1'' for the first track, ''2'' for the second, etc. You may
1424
-: also provide a list of tracks, separated by spaces or commas, for example
1425
-: '''-audiotrack 3,1,2'''. Use '''tovid id''' on your source video to determine
1426
-: which audio tracks it contains.
1427
-: 
1428
-; '''-downmix'''
1429
-: Encode all audio tracks as stereo.  This can save space on your DVD if
1430
-: your player only does stereo.  The default behavior of tovid is to use
1431
-: the original number of channels in each track.  For aac audio, downmixing
1432
-: is not possible: tovid runs a quick 1 frame test to try to downmix the
1433
-: input track with the largest number of channels, and if it fails then it
1434
-: will revert to the default behavior of using the original channels.
1435
-
1436
-==== Other options ====
1437
-
1438
-; '''-config''' ''FILE''
1439
-: Read configuration from ''FILE'', containing 'tovid' alone on the first
1440
-: line, and free-formatted (whitespace-separated) tovid command-line options
1441
-: on remaining lines.
1442
-: 
1443
-; '''-force'''
1444
-: Force encoding of already-compliant video or audio streams.
1445
-: 
1446
-; '''-overwrite'''
1447
-: Overwrite any existing output files (with the same name as the given
1448
-: '''-out''' option).
1449
-: 
1450
-; '''-priority''' {low|medium|high}
1451
-: Sets the main encoding process to the given priority. With high priority,
1452
-: it may take other programs longer to load and respond. With lower priority,
1453
-: other programs will be more responsive, but encoding may take 30-40%
1454
-: longer.  The default is high priority.
1455
-: 
1456
-; '''-discsize''' ''NUM''
1457
-: When encoding, tovid automatically splits the output file into several
1458
-: pieces if it exceeds the size of the target media. This option sets the
1459
-: desired target DVD/CD-R size to ''NUM'' mebibytes (MiB, 2^20). By default,
1460
-: splitting occurs at 700 for CD, 4300 for DVD. Use higher values at your
1461
-: own risk. Use 650 or lower if you plan to burn to smaller-capacity CDs.
1462
-: Doesn't work with the '''-ffmpeg''' option.
1463
-: 
1464
-; '''-fit''' ''NUM''
1465
-: Fit the output file into ''NUM'' MiB. Rather than using default (or
1466
-: specified) video bitrates, tovid will calculate the correct video bitrate
1467
-: that will limit the final output size to ''NUM'' MiB. This is different
1468
-: than '''-discsize''', which cuts the final file into ''NUM'' MiB pieces.
1469
-: '''-fit''' makes sure that the file never exceeds ''NUM'' MiB. This works
1470
-: with '''-ffmpeg''', but not with '''-vcd''' since VCDs have a standardized
1471
-: constant bitrate.
1472
-: 
1473
-; '''-parallel'''
1474
-: Perform ripping, encoding, and multiplexing processes in parallel using
1475
-: named pipes. Maximizes CPU utilization and minimizes disk usage. Note that
1476
-: this option simply does more tasks simultaneously, in order to make better
1477
-: use of available CPU cycles; it's unrelated to multi-CPU processing (which
1478
-: is done automatically anyway). Has no effect when '''-ffmpeg''' is used.
1479
-: 
1480
-; '''-update''' ''SECS''
1481
-: Print status updates at intervals of ''SECS'' seconds. This affects how
1482
-: regularly the progress-meter is updated. The default is once every five
1483
-: seconds.
1484
-: 
1485
-; '''-mpv'''
1486
-: Use mpv instead of mplayer. This option is experimental.
1487
-: 
1488
-; '''-mplayeropts''' ''OPTIONS''
1489
-: Append ''OPTIONS'' to the mplayer command run during video encoding.  Use
1490
-: this if you want to add specific video filters (documented in the mplayer
1491
-: manual page). Overriding some options will cause encoding to fail, so use
1492
-: this with caution!
1493
-: 
1494
-; '''-mpvopts''' ''OPTIONS''
1495
-: Append ''OPTIONS'' to the mpv command run during video encoding.  Use
1496
-: this if you want to add specific video filters (documented in the mplayer
1497
-: or mpv manual page). Overriding some options will cause encoding to fail,
1498
-: so use this with caution!
1499
-: 
1500
-; '''-nofifo''' (EXPERIMENTAL)
1501
-: Do not use a FIFO pipe for video encoding. If you are getting "Broken pipe"
1502
-: errors with normal encoding, try this option.  WARNING: This uses lots of
1503
-: disk space (about 2 GB per minute of video).
1504
-: 
1505
-; '''-keepfiles'''
1506
-: Keep the intermediate files after encoding. Usually, this means the audio
1507
-: and video streams are kept (eg the .ac3 and .m2v files for an NTSC DVD).
1508
-: This doesn't work with -parallel because the intermediate files are named
1509
-: pipes, and not real files.
1510
-: 
1511
-; '''-slice''' ''START''-''END''
1512
-: Encode a segment from ''START'' to ''END'' (in seconds). Only works with
1513
-: -ffmpeg.
1514
-: 
1515
-; '''-from-gui'''
1516
-: Put makempg into a fully non-interactive state, suitable for calling from
1517
-: a gui.
1518
-: 
1519
-; '''-noask'''
1520
-: Don't ask questions when choices need to be made. Assume reasonable
1521
-: answers.
1522
-
1523
-== Command:id ==
1524
-
1525
-'''tovid id''' identifies each multimedia video file in a
1526
-list, and reports its compliance with video disc standards such as VCD,
1527
-SVCD, and DVD.
1528
-
1529
-=== Usage ===
1530
-
1531
-'''tovid id''' [''OPTIONS''] ''VIDEO_FILE(s)''
1532
-
1533
-For example:
1534
-
1535
-; <tt>tovid id foo.avi</tt>
1536
-; <tt>tovid id -tabluar videos/*.mpg</tt>
1537
-
1538
-=== Options ===
1539
-
1540
-; '''-terse'''
1541
-: Print raw video characteristics, no formatting. Helpful when
1542
-: calling from other scripts.
1543
-: 
1544
-; '''-verbose'''
1545
-: Print extra information from mplayer, tcprobe, and ffmpeg.
1546
-: 
1547
-; '''-accurate'''
1548
-: Do lengthy play-time estimation by scanning through the entire video file.
1549
-: Use this if the default behavior is giving you inaccurate play times.
1550
-: 
1551
-; '''-fast'''
1552
-: Skip lengthy play-time estimation, and go with what mplayer reports
1553
-: as being the video duration. Unlike pre-0.32 versions of tovid, this
1554
-: is now the default behavior, and the '''-fast''' option doesn't do anything.
1555
-: 
1556
-; '''-tabular'''
1557
-: Display output in a table format for easier comparison. Most useful
1558
-: when identifying multiple video files.
1559
-: 
1560
-; '''-keepfiles'''
1561
-: Keep temporary directory for debugging.
1562
-: 
1563
-; '''-isformat''' [''pal-dvd''|''ntsc-dvd''] (same syntax for vcd and svcd)
1564
-: Check ''VIDEO_FILE'' for compliance with the given disc format.
1565
-: If ''VIDEO_FILE'' matches the given format, then '''tovid id''' reports "true"
1566
-: and exits successfully. Otherwise, '''tovid id''' reports "false" and exits
1567
-: with status 1 (failure).  This checks and reports both vcd/svcd/dvd
1568
-: and pal/ntsc.
1569
-: 
1570
-; '''-mpv'''
1571
-: This option is mainly for testing. If you have only mpv installed instead
1572
-: of mplayer, it is used automatically. With this option, you can have BOTH
1573
-: installed and choose which one to use. (default: mplayer)
1574
-
1575
-=== Examples ===
1576
-
1577
-; <tt>tovid id -verbose homevideo.avi</tt>
1578
-: Report everything mplayer, ffmpeg, and transcode can determine about
1579
-: homevideo.avi.
1580
-: 
1581
-; <tt>tovid id -isformat dvd homevideo.mpg</tt>
1582
-: Check to see if homevideo.mpg is compliant with the DVD standard.
1583
-
1584
-== Command:dvd ==
1585
-
1586
-'''tovid dvd''' takes a DVD directory as generated by tovid with 'tovid disc' or
1587
-one of the GUI frontends like 'tovid gui' or 'tovid titlesets' and burns
1588
-it to appropriate media.  This will also work if the DVD directory is
1589
-generated by the dvdauthor backend that tovid also uses.
1590
-
1591
-Running this program may slow down your other applications, due to intense
1592
-disk activity.
1593
-
1594
-=== Usage ===
1595
-
1596
-'''tovid dvd''' [''OPTIONS''] ''DVD_DIR''
1597
-
1598
-For example:
1599
-
1600
-; <tt>tovid dvd /path/to/DVD/directory</tt>
1601
-
1602
-=== Options ===
1603
-
1604
-; '''-burn'''
1605
-: Burn a DVD file-system in ''DVD_DIR'' (must contain a VIDEO_TS folder).
1606
-: This option is currently not necessary as the makedvd script ONLY burns
1607
-: now that legacy scripts like makexml have been removed.  Left for
1608
-: compatibility only.
1609
-: 
1610
-; '''-eject'''
1611
-: Eject the DVD tray after burning is complete. By default, the DVD is not
1612
-: ejected.
1613
-: 
1614
-; '''-device''' ''DEVICE'' (default /dev/dvdrw)
1615
-: Burn the disc image to ''DEVICE'', the Linux device file-system
1616
-: name of your DVD-recorder. Common examples might be /dev/dvdrw,
1617
-: /dev/scd1, and /dev/hdc. You can also use a bus/id/lun triple
1618
-: such as ATAPI:0,1,0
1619
-: 
1620
-; '''-speed''' ''NUM'' (default 1)
1621
-: Burn disc at speed ''NUM''.
1622
-: 
1623
-; '''-label''' ''DISC_LABEL''
1624
-: Uses ''DISC_LABEL'' as the volume ID. This appears as the mount
1625
-: name of the disc on some computer platforms. Must be <=32
1626
-: alphanumeric digits without spaces.
1627
-: 
1628
-; '''-quiet'''
1629
-: Limit output to essential messages.
1630
-: 
1631
-; '''-noask'''
1632
-: Don't ask interactive questions and assume answers that will continue
1633
-: execution.
1634
-
1635
-    After burning, the DVD can be previewed by calling:
1636
-    '''''xine''' dvd:/path/to/output/directory''
1637
-    or:
1638
-    '''''vlc''' /path/to/output/directory''
1639
-
1640
-== Command:chapters ==
1641
-
1642
-'''tovid chapters''' will start a GUI using mplayer to set chapter points in a
1643
-video.  If the video plays through and you want to add more chapters you can
1644
-press the play button again, but remember that new chapter points will be
1645
-appended (in correct sequential order).  It will display the resulting chapter
1646
-points, and also output to a terminal (useful for scripts).  As well it will
1647
-give the option of saving the chapters string to a text file.
1648
-
1649
-Note that the 'tovid gui' now features a similar widget when you press the
1650
-chapters button on the opening page.
1651
-
1652
-=== Examples ===
1653
-
1654
-; <tt>tovid chapters foo.avi</tt>
1655
-: 
1656
-; <tt>chapters=$(tovid chapters /home/grepper/videos/foo.avi)</tt>
1657
-
1658
-== CONTACT ==
1659
-
1660
-For further assistance, contact information, forum and IRC links,
1661
-please refer to the [http://tovid.wikia.com/ tovid homepage].
1662
-
1663
-<!-- wiki code generated by txt2tags 2.6 (http://txt2tags.org) -->
1664
-<!-- cmdline: txt2tags -t wiki -\-toc -\-toc-level 2 docs/src/en/tovid.t2t -->
1665
tovid-0.35.0.tar.gz/PKG-INFO -> tovid-0.35.2.tar.gz/PKG-INFO Changed
9
 
1
@@ -1,6 +1,6 @@
2
 Metadata-Version: 1.1
3
 Name: tovid
4
-Version: 0.35.0
5
+Version: 0.35.2
6
 Summary: A suite of tools for making video DVDs
7
 Home-page: http://tovid.wikia.com/
8
 Author: grepper
9
tovid-0.35.2.tar.gz/docs/scripts Added
2
 
1
+(directory)
2
tovid-0.35.2.tar.gz/docs/scripts/txt2tags Added
5989
 
1
@@ -0,0 +1,5987 @@
2
+#!/usr/bin/env python
3
+# txt2tags - generic text conversion tool ---> READY TO PYTHON 3!
4
+# http://txt2tags.org
5
+#
6
+# Copyright 2001-2010 Aurelio Jargas
7
+#
8
+# License: http://www.gnu.org/licenses/gpl-2.0.txt
9
+# Subversion: http://svn.txt2tags.org
10
+# Bug tracker: http://bugs.txt2tags.org
11
+#
12
+########################################################################
13
+#
14
+#   BORING CODE EXPLANATION AHEAD
15
+#
16
+# Just read it if you wish to understand how the txt2tags code works.
17
+#
18
+########################################################################
19
+#
20
+# The code that [1] parses the marked text is separated from the
21
+# code that [2] insert the target tags.
22
+#
23
+#   [1] made by: def convert()
24
+#   [2] made by: class BlockMaster
25
+#
26
+# The structures of the marked text are identified and its contents are
27
+# extracted into a data holder (Python lists and dictionaries).
28
+#
29
+# When parsing the source file, the blocks (para, lists, quote, table)
30
+# are opened with BlockMaster, right when found. Then its contents,
31
+# which spans on several lines, are feeded into a special holder on the
32
+# BlockMaster instance. Just when the block is closed, the target tags
33
+# are inserted for the full block as a whole, in one pass. This way, we
34
+# have a better control on blocks. Much better than the previous line by
35
+# line approach.
36
+#
37
+# In other words, whenever inside a block, the parser *holds* the tag
38
+# insertion process, waiting until the full block is read. That was
39
+# needed primary to close paragraphs for the XHTML target, but
40
+# proved to be a very good adding, improving many other processing.
41
+#
42
+# -------------------------------------------------------------------
43
+#
44
+# These important classes are all documented:
45
+# CommandLine, SourceDocument, ConfigMaster, ConfigLines.
46
+#
47
+# There is a RAW Config format and all kind of configuration is first
48
+# converted to this format. Then a generic method parses it.
49
+#
50
+# These functions get information about the input file(s) and take
51
+# care of the init processing:
52
+# get_infiles_config(), process_source_file() and convert_this_files()
53
+#
54
+########################################################################
55
+
56
+#XXX Python coding warning
57
+# Avoid common mistakes:
58
+# - do NOT use newlist=list instead newlist=list[:]
59
+# - do NOT use newdic=dic   instead newdic=dic.copy()
60
+# - do NOT use dic[key]     instead dic.get(key)
61
+# - do NOT use del dic[key] without has_key() before
62
+
63
+#XXX Smart Image Align don't work if the image is a link
64
+# Can't fix that because the image is expanded together with the
65
+# link, at the linkbank filling moment. Only the image is passed
66
+# to parse_images(), not the full line, so it is always 'middle'.
67
+
68
+#XXX Paragraph separation not valid inside Quote
69
+# Quote will not have <p></p> inside, instead will close and open
70
+# again the <blockquote>. This really sux in CSS, when defining a
71
+# different background color. Still don't know how to fix it.
72
+
73
+#XXX TODO (maybe)
74
+# New mark or macro which expands to an anchor full title.
75
+# It is necessary to parse the full document in this order:
76
+#  DONE  1st scan: HEAD: get all settings, including %!includeconf
77
+#  DONE  2nd scan: BODY: expand includes & apply %!preproc
78
+#        3rd scan: BODY: read titles and compose TOC info
79
+#        4th scan: BODY: full parsing, expanding [#anchor] 1st
80
+# Steps 2 and 3 can be made together, with no tag adding.
81
+# Two complete body scans will be *slow*, don't know if it worths.
82
+# One solution may be add the titles as postproc rules
83
+
84
+
85
+##############################################################################
86
+
87
+# User config (1=ON, 0=OFF)
88
+
89
+USE_I18N    = 1   # use gettext for i18ned messages?        (default is 1)
90
+COLOR_DEBUG = 1   # show debug messages in colors?          (default is 1)
91
+BG_LIGHT    = 0   # your terminal background color is light (default is 0)
92
+HTML_LOWER  = 0   # use lowercased HTML tags instead upper? (default is 0)
93
+
94
+##############################################################################
95
+
96
+
97
+# These are all the core Python modules used by txt2tags (KISS!)
98
+import re, os, sys, time, getopt
99
+
100
+# The CSV module is new in Python version 2.3
101
+try:
102
+   import csv
103
+except ImportError:
104
+   csv = None
105
+
106
+# Program information
107
+my_url = 'http://txt2tags.org'
108
+my_name = 'txt2tags'
109
+my_email = 'verde@aurelio.net'
110
+my_version = '2.6'
111
+
112
+# i18n - just use if available
113
+if USE_I18N:
114
+   try:
115
+       import gettext
116
+       # If your locale dir is different, change it here
117
+       cat = gettext.Catalog('txt2tags',localedir='/usr/share/locale/')
118
+       _ = cat.gettext
119
+   except:
120
+       _ = lambda x:x
121
+else:
122
+   _ = lambda x:x
123
+
124
+# FLAGS   : the conversion related flags  , may be used in %!options
125
+# OPTIONS : the conversion related options, may be used in %!options
126
+# ACTIONS : the other behavior modifiers, valid on command line only
127
+# MACROS  : the valid macros with their default values for formatting
128
+# SETTINGS: global miscellaneous settings, valid on RC file only
129
+# NO_TARGET: actions that don't require a target specification
130
+# NO_MULTI_INPUT: actions that don't accept more than one input file
131
+# CONFIG_KEYWORDS: the valid %!key:val keywords
132
+#
133
+# FLAGS and OPTIONS are configs that affect the converted document.
134
+# They usually have also a --no-<option> to turn them OFF.
135
+#
136
+# ACTIONS are needed because when doing multiple input files, strange
137
+# behavior would be found, as use command line interface for the
138
+# first file and gui for the second. There is no --no-<action>.
139
+# --version and --help inside %!options are also odd
140
+#
141
+TARGETS  = sorted( 'html xhtml sgml dbk tex lout man mgp wiki gwiki doku pmw moin pm6 txt art adoc creole'.split() )
142
+
143
+FLAGS    = {'headers'    :1 , 'enum-title' :0 , 'mask-email' :0 ,
144
+            'toc-only'   :0 , 'toc'        :0 , 'rc'         :1 ,
145
+            'css-sugar'  :0 , 'css-suggar' :0 , 'css-inside' :0 ,
146
+            'quiet'      :0 , 'slides'     :0 }
147
+OPTIONS  = {'target'     :'', 'toc-level'  :3 , 'style'      :'',
148
+            'infile'     :'', 'outfile'    :'', 'encoding'   :'',
149
+            'config-file':'', 'split'      :0 , 'lang'       :'',
150
+            'width'      :0 , 'height'     :0 , 'art-chars'  :'',
151
+            'show-config-value':''}
152
+ACTIONS  = {'help'       :0 , 'version'    :0 , 'gui'        :0 ,
153
+            'verbose'    :0 , 'debug'      :0 , 'dump-config':0 ,
154
+            'dump-source':0 , 'targets'    :0}
155
+MACROS   = {'date' : '%Y%m%d',  'infile': '%f',
156
+            'mtime': '%Y%m%d', 'outfile': '%f'}
157
+SETTINGS = {}         # for future use
158
+NO_TARGET = ['help', 'version', 'gui', 'toc-only', 'dump-config', 'dump-source', 'targets']
159
+NO_MULTI_INPUT = ['gui','dump-config','dump-source']
160
+CONFIG_KEYWORDS = [
161
+            'target', 'encoding', 'style', 'options', 'preproc','postproc',
162
+            'guicolors']
163
+
164
+TARGET_NAMES = {
165
+  'html'   : _('HTML page'),
166
+  'xhtml'  : _('XHTML page'),
167
+  'sgml'   : _('SGML document'),
168
+  'dbk'    : _('DocBook document'),
169
+  'tex'    : _('LaTeX document'),
170
+  'lout'   : _('Lout document'),
171
+  'man'    : _('UNIX Manual page'),
172
+  'mgp'    : _('MagicPoint presentation'),
173
+  'wiki'   : _('Wikipedia page'),
174
+  'gwiki'  : _('Google Wiki page'),
175
+  'doku'   : _('DokuWiki page'),
176
+  'pmw'    : _('PmWiki page'),
177
+  'moin'   : _('MoinMoin page'),
178
+  'pm6'    : _('PageMaker document'),
179
+  'txt'    : _('Plain Text'),
180
+  'art'    : _('ASCII Art text'),
181
+  'adoc'   : _('AsciiDoc document'),
182
+  'creole' : _('Creole 1.0 document')
183
+}
184
+
185
+DEBUG = 0     # do not edit here, please use --debug
186
+VERBOSE = 0   # do not edit here, please use -v, -vv or -vvv
187
+QUIET = 0     # do not edit here, please use --quiet
188
+GUI = 0       # do not edit here, please use --gui
189
+AUTOTOC = 1   # do not edit here, please use --no-toc or %%toc
190
+
191
+DFT_TEXT_WIDTH   = 72 # do not edit here, please use --width
192
+DFT_SLIDE_WIDTH  = 80 # do not edit here, please use --width
193
+DFT_SLIDE_HEIGHT = 25 # do not edit here, please use --height
194
+
195
+# ASCII Art config
196
+AA_KEYS = 'corner border side bar1 bar2 level2 level3 level4 level5'.split()
197
+AA_VALUES = '+-|-==-^"' # do not edit here, please use --art-chars
198
+AA = dict(zip(AA_KEYS, AA_VALUES))
199
+AA_COUNT = 0
200
+AA_TITLE = ''
201
+
202
+RC_RAW = []
203
+CMDLINE_RAW = []
204
+CONF = {}
205
+BLOCK = None
206
+TITLE = None
207
+regex = {}
208
+TAGS = {}
209
+rules = {}
210
+
211
+# Gui globals
212
+askopenfilename = None
213
+showinfo = None
214
+showwarning = None
215
+showerror = None
216
+
217
+lang = 'english'
218
+TARGET = ''
219
+
220
+STDIN = STDOUT = '-'
221
+MODULEIN = MODULEOUT = '-module-'
222
+ESCCHAR   = '\x00'
223
+SEPARATOR = '\x01'
224
+LISTNAMES = {'-':'list', '+':'numlist', ':':'deflist'}
225
+LINEBREAK = {'default':'\n', 'win':'\r\n', 'mac':'\r'}
226
+
227
+# Platform specific settings
228
+LB = LINEBREAK.get(sys.platform[:3]) or LINEBREAK['default']
229
+
230
+VERSIONSTR = _("%s version %s <%s>")%(my_name,my_version,my_url)
231
+
232
+USAGE =  '\n'.join([
233
+'',
234
+_("Usage: %s [OPTIONS] [infile.t2t ...]") % my_name,
235
+'',
236
+_("      --targets       print a list of all the available targets and exit"),
237
+_("  -t, --target=TYPE   set target document type. currently supported:"),
238
+  '                      %s,' % ', '.join(TARGETS[:9]),
239
+  '                      %s'  % ', '.join(TARGETS[9:]),
240
+_("  -i, --infile=FILE   set FILE as the input file name ('-' for STDIN)"),
241
+_("  -o, --outfile=FILE  set FILE as the output file name ('-' for STDOUT)"),
242
+_("      --encoding=ENC  set target file encoding (utf-8, iso-8859-1, etc)"),
243
+_("      --toc           add an automatic Table of Contents to the output"),
244
+_("      --toc-level=N   set maximum TOC level (depth) to N"),
245
+_("      --toc-only      print the Table of Contents and exit"),
246
+_("  -n, --enum-title    enumerate all titles as 1, 1.1, 1.1.1, etc"),
247
+_("      --style=FILE    use FILE as the document style (like HTML CSS)"),
248
+_("      --css-sugar     insert CSS-friendly tags for HTML/XHTML"),
249
+_("      --css-inside    insert CSS file contents inside HTML/XHTML headers"),
250
+_("  -H, --no-headers    suppress header and footer from the output"),
251
+_("      --mask-email    hide email from spam robots. x@y.z turns <x (a) y z>"),
252
+_("      --slides        format output as presentation slides (used by -t art)"),
253
+_("      --width=N       set the output's width to N columns (used by -t art)"),
254
+_("      --height=N      set the output's height to N rows (used by -t art)"),
255
+_("  -C, --config-file=F read configuration from file F"),
256
+_("      --gui           invoke Graphical Tk Interface"),
257
+_("  -q, --quiet         quiet mode, suppress all output (except errors)"),
258
+_("  -v, --verbose       print informative messages during conversion"),
259
+_("  -h, --help          print this help information and exit"),
260
+_("  -V, --version       print program version and exit"),
261
+_("      --dump-config   print all the configuration found and exit"),
262
+_("      --dump-source   print the document source, with includes expanded"),
263
+'',
264
+_("Turn OFF options:"),
265
+"     --no-css-inside, --no-css-sugar, --no-dump-config, --no-dump-source,",
266
+"     --no-encoding, --no-enum-title, --no-headers, --no-infile,",
267
+"     --no-mask-email, --no-outfile, --no-quiet, --no-rc, --no-slides,",
268
+"     --no-style, --no-targets, --no-toc, --no-toc-only",
269
+'',
270
+_("Example:"),
271
+"     %s -t html --toc %s" % (my_name, _("file.t2t")),
272
+'',
273
+_("By default, converted output is saved to 'infile.<target>'."),
274
+_("Use --outfile to force an output file name."),
275
+_("If  input file is '-', reads from STDIN."),
276
+_("If output file is '-', dumps output to STDOUT."),
277
+'',
278
+my_url,
279
+''
280
+])
281
+
282
+
283
+##############################################################################
284
+
285
+
286
+# Here is all the target's templates
287
+# You may edit them to fit your needs
288
+#  - the %(HEADERn)s strings represent the Header lines
289
+#  - the %(STYLE)s string is changed by --style contents
290
+#  - the %(ENCODING)s string is changed by --encoding contents
291
+#  - if any of the above is empty, the full line is removed
292
+#  - use %% to represent a literal %
293
+#
294
+HEADER_TEMPLATE = {
295
+   'art':"""
296
+Fake template to respect the general process.
297
+""",
298
+   'txt': """\
299
+%(HEADER1)s
300
+%(HEADER2)s
301
+%(HEADER3)s
302
+""",
303
+
304
+   'sgml': """\
305
+<!doctype linuxdoc system>
306
+<article>
307
+<title>%(HEADER1)s
308
+<author>%(HEADER2)s
309
+<date>%(HEADER3)s
310
+""",
311
+
312
+   'html': """\
313
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
314
+<HTML>
315
+<HEAD>
316
+<META NAME="generator" CONTENT="http://txt2tags.org">
317
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=%(ENCODING)s">
318
+<LINK REL="stylesheet" TYPE="text/css" HREF="%(STYLE)s">
319
+<TITLE>%(HEADER1)s</TITLE>
320
+</HEAD><BODY BGCOLOR="white" TEXT="black">
321
+<CENTER>
322
+<H1>%(HEADER1)s</H1>
323
+<FONT SIZE="4"><I>%(HEADER2)s</I></FONT><BR>
324
+<FONT SIZE="4">%(HEADER3)s</FONT>
325
+</CENTER>
326
+""",
327
+
328
+   'htmlcss': """\
329
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
330
+<HTML>
331
+<HEAD>
332
+<META NAME="generator" CONTENT="http://txt2tags.org">
333
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=%(ENCODING)s">
334
+<LINK REL="stylesheet" TYPE="text/css" HREF="%(STYLE)s">
335
+<TITLE>%(HEADER1)s</TITLE>
336
+</HEAD>
337
+<BODY>
338
+
339
+<DIV CLASS="header" ID="header">
340
+<H1>%(HEADER1)s</H1>
341
+<H2>%(HEADER2)s</H2>
342
+<H3>%(HEADER3)s</H3>
343
+</DIV>
344
+""",
345
+
346
+   'xhtml': """\
347
+<?xml version="1.0"
348
+      encoding="%(ENCODING)s"
349
+?>
350
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"\
351
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
352
+<html xmlns="http://www.w3.org/1999/xhtml">
353
+<head>
354
+<title>%(HEADER1)s</title>
355
+<meta name="generator" content="http://txt2tags.org" />
356
+<link rel="stylesheet" type="text/css" href="%(STYLE)s" />
357
+</head>
358
+<body bgcolor="white" text="black">
359
+<div align="center">
360
+<h1>%(HEADER1)s</h1>
361
+<h2>%(HEADER2)s</h2>
362
+<h3>%(HEADER3)s</h3>
363
+</div>
364
+""",
365
+
366
+   'xhtmlcss': """\
367
+<?xml version="1.0"
368
+      encoding="%(ENCODING)s"
369
+?>
370
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"\
371
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
372
+<html xmlns="http://www.w3.org/1999/xhtml">
373
+<head>
374
+<title>%(HEADER1)s</title>
375
+<meta name="generator" content="http://txt2tags.org" />
376
+<link rel="stylesheet" type="text/css" href="%(STYLE)s" />
377
+</head>
378
+<body>
379
+
380
+<div class="header" id="header">
381
+<h1>%(HEADER1)s</h1>
382
+<h2>%(HEADER2)s</h2>
383
+<h3>%(HEADER3)s</h3>
384
+</div>
385
+""",
386
+
387
+   'dbk': """\
388
+<?xml version="1.0"
389
+      encoding="%(ENCODING)s"
390
+?>
391
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"\
392
+ "docbook/dtd/xml/4.5/docbookx.dtd">
393
+<article lang="en">
394
+  <articleinfo>
395
+    <title>%(HEADER1)s</title>
396
+    <authorgroup>
397
+      <author><othername>%(HEADER2)s</othername></author>
398
+    </authorgroup>
399
+    <date>%(HEADER3)s</date>
400
+  </articleinfo>
401
+""",
402
+
403
+   'man': """\
404
+.TH "%(HEADER1)s" 1 "%(HEADER3)s" "%(HEADER2)s"
405
+""",
406
+
407
+# TODO style to <HR>
408
+   'pm6': """\
409
+<PMTags1.0 win><C-COLORTABLE ("Preto" 1 0 0 0)
410
+><@Normal=
411
+  <FONT "Times New Roman"><CCOLOR "Preto"><SIZE 11>
412
+  <HORIZONTAL 100><LETTERSPACE 0><CTRACK 127><CSSIZE 70><C+SIZE 58.3>
413
+  <C-POSITION 33.3><C+POSITION 33.3><P><CBASELINE 0><CNOBREAK 0><CLEADING -0.05>
414
+  <GGRID 0><GLEFT 7.2><GRIGHT 0><GFIRST 0><G+BEFORE 7.2><G+AFTER 0>
415
+  <GALIGNMENT "justify"><GMETHOD "proportional"><G& "ENGLISH">
416
+  <GPAIRS 12><G%% 120><GKNEXT 0><GKWIDOW 0><GKORPHAN 0><GTABS $>
417
+  <GHYPHENATION 2 34 0><GWORDSPACE 75 100 150><GSPACE -5 0 25>
418
+><@Bullet=<@-PARENT "Normal"><FONT "Abadi MT Condensed Light">
419
+  <GLEFT 14.4><G+BEFORE 2.15><G%% 110><GTABS(25.2 l "")>
420
+><@PreFormat=<@-PARENT "Normal"><FONT "Lucida Console"><SIZE 8><CTRACK 0>
421
+  <GLEFT 0><G+BEFORE 0><GALIGNMENT "left"><GWORDSPACE 100 100 100><GSPACE 0 0 0>
422
+><@Title1=<@-PARENT "Normal"><FONT "Arial"><SIZE 14><B>
423
+  <GCONTENTS><GLEFT 0><G+BEFORE 0><GALIGNMENT "left">
424
+><@Title2=<@-PARENT "Title1"><SIZE 12><G+BEFORE 3.6>
425
+><@Title3=<@-PARENT "Title1"><SIZE 10><GLEFT 7.2><G+BEFORE 7.2>
426
+><@Title4=<@-PARENT "Title3">
427
+><@Title5=<@-PARENT "Title3">
428
+><@Quote=<@-PARENT "Normal"><SIZE 10><I>>
429
+
430
+%(HEADER1)s
431
+%(HEADER2)s
432
+%(HEADER3)s
433
+""",
434
+
435
+   'mgp': """\
436
+#!/usr/X11R6/bin/mgp -t 90
437
+%%deffont "normal"    xfont  "utopia-medium-r", charset "iso8859-1"
438
+%%deffont "normal-i"  xfont  "utopia-medium-i", charset "iso8859-1"
439
+%%deffont "normal-b"  xfont  "utopia-bold-r"  , charset "iso8859-1"
440
+%%deffont "normal-bi" xfont  "utopia-bold-i"  , charset "iso8859-1"
441
+%%deffont "mono"      xfont "courier-medium-r", charset "iso8859-1"
442
+%%default 1 size 5
443
+%%default 2 size 8, fore "yellow", font "normal-b", center
444
+%%default 3 size 5, fore "white",  font "normal", left, prefix "  "
445
+%%tab 1 size 4, vgap 30, prefix "     ", icon arc "red" 40, leftfill
446
+%%tab 2 prefix "            ", icon arc "orange" 40, leftfill
447
+%%tab 3 prefix "                   ", icon arc "brown" 40, leftfill
448
+%%tab 4 prefix "                          ", icon arc "darkmagenta" 40, leftfill
449
+%%tab 5 prefix "                                ", icon arc "magenta" 40, leftfill
450
+%%%%------------------------- end of headers -----------------------------
451
+%%page
452
+
453
+
454
+
455
+
456
+
457
+%%size 10, center, fore "yellow"
458
+%(HEADER1)s
459
+
460
+%%font "normal-i", size 6, fore "white", center
461
+%(HEADER2)s
462
+
463
+%%font "mono", size 7, center
464
+%(HEADER3)s
465
+""",
466
+
467
+   'moin': """\
468
+'''%(HEADER1)s'''
469
+
470
+''%(HEADER2)s''
471
+
472
+%(HEADER3)s
473
+""",
474
+
475
+   'gwiki': """\
476
+*%(HEADER1)s*
477
+
478
+%(HEADER2)s
479
+
480
+_%(HEADER3)s_
481
+""",
482
+
483
+   'adoc': """\
484
+= %(HEADER1)s
485
+%(HEADER2)s
486
+%(HEADER3)s
487
+""",
488
+
489
+   'doku': """\
490
+===== %(HEADER1)s =====
491
+
492
+**//%(HEADER2)s//**
493
+
494
+//%(HEADER3)s//
495
+""",
496
+
497
+   'pmw': """\
498
+(:Title %(HEADER1)s:)
499
+
500
+(:Description %(HEADER2)s:)
501
+
502
+(:Summary %(HEADER3)s:)
503
+""",
504
+
505
+   'wiki': """\
506
+'''%(HEADER1)s'''
507
+
508
+%(HEADER2)s
509
+
510
+''%(HEADER3)s''
511
+""",
512
+
513
+   'tex': \
514
+r"""\documentclass{article}
515
+\usepackage{graphicx}
516
+\usepackage{paralist} %% needed for compact lists
517
+\usepackage[normalem]{ulem} %% needed by strike
518
+\usepackage[urlcolor=blue,colorlinks=true]{hyperref}
519
+\usepackage[%(ENCODING)s]{inputenc}  %% char encoding
520
+\usepackage{%(STYLE)s}  %% user defined
521
+
522
+\title{%(HEADER1)s}
523
+\author{%(HEADER2)s}
524
+\begin{document}
525
+\date{%(HEADER3)s}
526
+\maketitle
527
+\clearpage
528
+""",
529
+
530
+   'lout': """\
531
+@SysInclude { doc }
532
+@Document
533
+  @InitialFont { Times Base 12p }  # Times, Courier, Helvetica, ...
534
+  @PageOrientation { Portrait }    # Portrait, Landscape
535
+  @ColumnNumber { 1 }              # Number of columns (2, 3, ...)
536
+  @PageHeaders { Simple }          # None, Simple, Titles, NoTitles
537
+  @InitialLanguage { English }     # German, French, Portuguese, ...
538
+  @OptimizePages { Yes }           # Yes/No smart page break feature
539
+//
540
+@Text @Begin
541
+@Display @Heading { %(HEADER1)s }
542
+@Display @I { %(HEADER2)s }
543
+@Display { %(HEADER3)s }
544
+#@NP                               # Break page after Headers
545
+""",
546
+   'creole': """\
547
+%(HEADER1)s
548
+%(HEADER2)s
549
+%(HEADER3)s
550
+"""
551
+# @SysInclude { tbl }                   # Tables support
552
+# setup: @MakeContents { Yes }          # show TOC
553
+# setup: @SectionGap                    # break page at each section
554
+}
555
+
556
+
557
+##############################################################################
558
+
559
+
560
+def getTags(config):
561
+   "Returns all the known tags for the specified target"
562
+   
563
+   keys = """
564
+   title1              numtitle1
565
+   title2              numtitle2
566
+   title3              numtitle3
567
+   title4              numtitle4
568
+   title5              numtitle5
569
+   title1Open          title1Close
570
+   title2Open          title2Close
571
+   title3Open          title3Close
572
+   title4Open          title4Close
573
+   title5Open          title5Close
574
+   blocktitle1Open     blocktitle1Close
575
+   blocktitle2Open     blocktitle2Close
576
+   blocktitle3Open     blocktitle3Close
577
+
578
+   paragraphOpen       paragraphClose
579
+   blockVerbOpen       blockVerbClose
580
+   blockQuoteOpen      blockQuoteClose blockQuoteLine
581
+   blockCommentOpen    blockCommentClose
582
+
583
+   fontMonoOpen        fontMonoClose
584
+   fontBoldOpen        fontBoldClose
585
+   fontItalicOpen      fontItalicClose
586
+   fontUnderlineOpen   fontUnderlineClose
587
+   fontStrikeOpen      fontStrikeClose
588
+
589
+   listOpen            listClose
590
+   listOpenCompact     listCloseCompact
591
+   listItemOpen        listItemClose     listItemLine
592
+   numlistOpen         numlistClose
593
+   numlistOpenCompact  numlistCloseCompact
594
+   numlistItemOpen     numlistItemClose  numlistItemLine
595
+   deflistOpen         deflistClose
596
+   deflistOpenCompact  deflistCloseCompact
597
+   deflistItem1Open    deflistItem1Close
598
+   deflistItem2Open    deflistItem2Close deflistItem2LinePrefix
599
+
600
+   bar1                bar2
601
+   url                 urlMark
602
+   email               emailMark
603
+   img                 imgAlignLeft  imgAlignRight  imgAlignCenter
604
+                      _imgAlignLeft _imgAlignRight _imgAlignCenter
605
+
606
+   tableOpen           tableClose
607
+   _tableBorder        _tableAlignLeft      _tableAlignCenter
608
+   tableRowOpen        tableRowClose        tableRowSep
609
+   tableTitleRowOpen   tableTitleRowClose
610
+   tableCellOpen       tableCellClose       tableCellSep
611
+   tableTitleCellOpen  tableTitleCellClose  tableTitleCellSep
612
+   _tableColAlignLeft  _tableColAlignRight  _tableColAlignCenter
613
+   _tableCellAlignLeft _tableCellAlignRight _tableCellAlignCenter
614
+   _tableCellColSpan   tableColAlignSep
615
+   _tableCellMulticolOpen
616
+   _tableCellMulticolClose
617
+
618
+   bodyOpen            bodyClose
619
+   cssOpen             cssClose
620
+   tocOpen             tocClose             TOC
621
+   anchor
622
+   comment
623
+   pageBreak
624
+   EOD
625
+   """.split()
626
+   
627
+   # TIP: \a represents the current text inside the mark
628
+   # TIP: ~A~, ~B~ and ~C~ are expanded to other tags parts
629
+   
630
+   alltags = {
631
+   
632
+   'art': {
633
+       'title1'               : '\a'                     ,
634
+       'title2'               : '\a'                     ,
635
+       'title3'               : '\a'                     ,
636
+       'title4'               : '\a'                     ,
637
+       'title5'               : '\a'                     ,
638
+       'blockQuoteLine'       : '\t'                     ,
639
+       'listItemOpen'         : '- '                     ,
640
+       'numlistItemOpen'      : '\a. '                   ,
641
+       'bar1'                 : aa_line(AA['bar1'], config['width']),
642
+       'bar2'                 : aa_line(AA['bar2'], config['width']),
643
+       'url'                  : '\a'                     ,
644
+       'urlMark'              : '\a (\a)'                ,
645
+       'email'                : '\a'                     ,
646
+       'emailMark'            : '\a (\a)'                ,
647
+       'img'                  : '[\a]'                   ,
648
+   },
649
+   
650
+   'txt': {
651
+       'title1'               : '  \a'      ,
652
+       'title2'               : '\t\a'      ,
653
+       'title3'               : '\t\t\a'    ,
654
+       'title4'               : '\t\t\t\a'  ,
655
+       'title5'               : '\t\t\t\t\a',
656
+       'blockQuoteLine'       : '\t'        ,
657
+       'listItemOpen'         : '- '        ,
658
+       'numlistItemOpen'      : '\a. '      ,
659
+       'bar1'                 : '\a'        ,
660
+       'url'                  : '\a'        ,
661
+       'urlMark'              : '\a (\a)'   ,
662
+       'email'                : '\a'        ,
663
+       'emailMark'            : '\a (\a)'   ,
664
+       'img'                  : '[\a]'      ,
665
+   },
666
+   
667
+   'html': {
668
+       'paragraphOpen'        : '<P>'            ,
669
+       'paragraphClose'       : '</P>'           ,
670
+       'title1'               : '~A~<H1>\a</H1>' ,
671
+       'title2'               : '~A~<H2>\a</H2>' ,
672
+       'title3'               : '~A~<H3>\a</H3>' ,
673
+       'title4'               : '~A~<H4>\a</H4>' ,
674
+       'title5'               : '~A~<H5>\a</H5>' ,
675
+       'anchor'               : '<A NAME="\a"></A>\n',
676
+       'blockVerbOpen'        : '<PRE>'          ,
677
+       'blockVerbClose'       : '</PRE>'         ,
678
+       'blockQuoteOpen'       : '<BLOCKQUOTE>'   ,
679
+       'blockQuoteClose'      : '</BLOCKQUOTE>'  ,
680
+       'fontMonoOpen'         : '<CODE>'         ,
681
+       'fontMonoClose'        : '</CODE>'        ,
682
+       'fontBoldOpen'         : '<B>'            ,
683
+       'fontBoldClose'        : '</B>'           ,
684
+       'fontItalicOpen'       : '<I>'            ,
685
+       'fontItalicClose'      : '</I>'           ,
686
+       'fontUnderlineOpen'    : '<U>'            ,
687
+       'fontUnderlineClose'   : '</U>'           ,
688
+       'fontStrikeOpen'       : '<S>'            ,
689
+       'fontStrikeClose'      : '</S>'           ,
690
+       'listOpen'             : '<UL>'           ,
691
+       'listClose'            : '</UL>'          ,
692
+       'listItemOpen'         : '<LI>'           ,
693
+       'numlistOpen'          : '<OL>'           ,
694
+       'numlistClose'         : '</OL>'          ,
695
+       'numlistItemOpen'      : '<LI>'           ,
696
+       'deflistOpen'          : '<DL>'           ,
697
+       'deflistClose'         : '</DL>'          ,
698
+       'deflistItem1Open'     : '<DT>'           ,
699
+       'deflistItem1Close'    : '</DT>'          ,
700
+       'deflistItem2Open'     : '<DD>'           ,
701
+       'bar1'                 : '<HR NOSHADE SIZE=1>'        ,
702
+       'bar2'                 : '<HR NOSHADE SIZE=5>'        ,
703
+       'url'                  : '<A HREF="\a">\a</A>'        ,
704
+       'urlMark'              : '<A HREF="\a">\a</A>'        ,
705
+       'email'                : '<A HREF="mailto:\a">\a</A>' ,
706
+       'emailMark'            : '<A HREF="mailto:\a">\a</A>' ,
707
+       'img'                  : '<IMG~A~ SRC="\a" BORDER="0" ALT="">',
708
+       '_imgAlignLeft'        : ' ALIGN="left"'  ,
709
+       '_imgAlignCenter'      : ' ALIGN="middle"',
710
+       '_imgAlignRight'       : ' ALIGN="right"' ,
711
+       'tableOpen'            : '<TABLE~A~~B~ CELLPADDING="4">',
712
+       'tableClose'           : '</TABLE>'       ,
713
+       'tableRowOpen'         : '<TR>'           ,
714
+       'tableRowClose'        : '</TR>'          ,
715
+       'tableCellOpen'        : '<TD~A~~S~>'     ,
716
+       'tableCellClose'       : '</TD>'          ,
717
+       'tableTitleCellOpen'   : '<TH~S~>'        ,
718
+       'tableTitleCellClose'  : '</TH>'          ,
719
+       '_tableBorder'         : ' BORDER="1"'    ,
720
+       '_tableAlignCenter'    : ' ALIGN="center"',
721
+       '_tableCellAlignRight' : ' ALIGN="right"' ,
722
+       '_tableCellAlignCenter': ' ALIGN="center"',
723
+       '_tableCellColSpan'    : ' COLSPAN="\a"'  ,
724
+       'cssOpen'              : '<STYLE TYPE="text/css">',
725
+       'cssClose'             : '</STYLE>'       ,
726
+       'comment'              : '<!-- \a -->'    ,
727
+       'EOD'                  : '</BODY></HTML>'
728
+   },
729
+   
730
+   #TIP xhtml inherits all HTML definitions (lowercased)
731
+   #TIP http://www.w3.org/TR/xhtml1/#guidelines
732
+   #TIP http://www.htmlref.com/samples/Chapt17/17_08.htm
733
+   'xhtml': {
734
+       'listItemClose'        : '</li>'          ,
735
+       'numlistItemClose'     : '</li>'          ,
736
+       'deflistItem2Close'    : '</dd>'          ,
737
+       'bar1'                 : '<hr class="light" />',
738
+       'bar2'                 : '<hr class="heavy" />',
739
+       'anchor'               : '<a id="\a" name="\a"></a>\n',
740
+       'img'                  : '<img~A~ src="\a" border="0" alt=""/>',
741
+   },
742
+   
743
+   'sgml': {
744
+       'paragraphOpen'        : '<p>'                ,
745
+       'title1'               : '<sect>\a~A~<p>'     ,
746
+       'title2'               : '<sect1>\a~A~<p>'    ,
747
+       'title3'               : '<sect2>\a~A~<p>'    ,
748
+       'title4'               : '<sect3>\a~A~<p>'    ,
749
+       'title5'               : '<sect4>\a~A~<p>'    ,
750
+       'anchor'               : '<label id="\a">'    ,
751
+       'blockVerbOpen'        : '<tscreen><verb>'    ,
752
+       'blockVerbClose'       : '</verb></tscreen>'  ,
753
+       'blockQuoteOpen'       : '<quote>'            ,
754
+       'blockQuoteClose'      : '</quote>'           ,
755
+       'fontMonoOpen'         : '<tt>'               ,
756
+       'fontMonoClose'        : '</tt>'              ,
757
+       'fontBoldOpen'         : '<bf>'               ,
758
+       'fontBoldClose'        : '</bf>'              ,
759
+       'fontItalicOpen'       : '<em>'               ,
760
+       'fontItalicClose'      : '</em>'              ,
761
+       'fontUnderlineOpen'    : '<bf><em>'           ,
762
+       'fontUnderlineClose'   : '</em></bf>'         ,
763
+       'listOpen'             : '<itemize>'          ,
764
+       'listClose'            : '</itemize>'         ,
765
+       'listItemOpen'         : '<item>'             ,
766
+       'numlistOpen'          : '<enum>'             ,
767
+       'numlistClose'         : '</enum>'            ,
768
+       'numlistItemOpen'      : '<item>'             ,
769
+       'deflistOpen'          : '<descrip>'          ,
770
+       'deflistClose'         : '</descrip>'         ,
771
+       'deflistItem1Open'     : '<tag>'              ,
772
+       'deflistItem1Close'    : '</tag>'             ,
773
+       'bar1'                 : '<!-- \a -->'        ,
774
+       'url'                  : '<htmlurl url="\a" name="\a">'        ,
775
+       'urlMark'              : '<htmlurl url="\a" name="\a">'        ,
776
+       'email'                : '<htmlurl url="mailto:\a" name="\a">' ,
777
+       'emailMark'            : '<htmlurl url="mailto:\a" name="\a">' ,
778
+       'img'                  : '<figure><ph vspace=""><img src="\a"></figure>',
779
+       'tableOpen'            : '<table><tabular ca="~C~">'           ,
780
+       'tableClose'           : '</tabular></table>' ,
781
+       'tableRowSep'          : '<rowsep>'           ,
782
+       'tableCellSep'         : '<colsep>'           ,
783
+       '_tableColAlignLeft'   : 'l'                  ,
784
+       '_tableColAlignRight'  : 'r'                  ,
785
+       '_tableColAlignCenter' : 'c'                  ,
786
+       'comment'              : '<!-- \a -->'        ,
787
+       'TOC'                  : '<toc>'              ,
788
+       'EOD'                  : '</article>'
789
+   },
790
+   
791
+   'dbk': {
792
+       'paragraphOpen'        : '<para>'                            ,
793
+       'paragraphClose'       : '</para>'                           ,
794
+       'title1Open'           : '~A~<sect1><title>\a</title>'       ,
795
+       'title1Close'          : '</sect1>'                          ,
796
+       'title2Open'           : '~A~  <sect2><title>\a</title>'     ,
797
+       'title2Close'          : '  </sect2>'                        ,
798
+       'title3Open'           : '~A~    <sect3><title>\a</title>'   ,
799
+       'title3Close'          : '    </sect3>'                      ,
800
+       'title4Open'           : '~A~      <sect4><title>\a</title>' ,
801
+       'title4Close'          : '      </sect4>'                    ,
802
+       'title5Open'           : '~A~        <sect5><title>\a</title>',
803
+       'title5Close'          : '        </sect5>'                  ,
804
+       'anchor'               : '<anchor id="\a"/>\n'               ,
805
+       'blockVerbOpen'        : '<programlisting>'                  ,
806
+       'blockVerbClose'       : '</programlisting>'                 ,
807
+       'blockQuoteOpen'       : '<blockquote><para>'                ,
808
+       'blockQuoteClose'      : '</para></blockquote>'              ,
809
+       'fontMonoOpen'         : '<code>'                            ,
810
+       'fontMonoClose'        : '</code>'                           ,
811
+       'fontBoldOpen'         : '<emphasis role="bold">'            ,
812
+       'fontBoldClose'        : '</emphasis>'                       ,
813
+       'fontItalicOpen'       : '<emphasis>'                        ,
814
+       'fontItalicClose'      : '</emphasis>'                       ,
815
+       'fontUnderlineOpen'    : '<emphasis role="underline">'       ,
816
+       'fontUnderlineClose'   : '</emphasis>'                       ,
817
+       # 'fontStrikeOpen'       : '<emphasis role="strikethrough">'   , # Don't know
818
+       # 'fontStrikeClose'      : '</emphasis>'                       ,
819
+       'listOpen'             : '<itemizedlist>'                    ,
820
+       'listClose'            : '</itemizedlist>'                   ,
821
+       'listItemOpen'         : '<listitem><para>'                  ,
822
+       'listItemClose'        : '</para></listitem>'                ,
823
+       'numlistOpen'          : '<orderedlist numeration="arabic">' ,
824
+       'numlistClose'         : '</orderedlist>'                    ,
825
+       'numlistItemOpen'      : '<listitem><para>'                  ,
826
+       'numlistItemClose'     : '</para></listitem>'                ,
827
+       'deflistOpen'          : '<variablelist>'                    ,
828
+       'deflistClose'         : '</variablelist>'                   ,
829
+       'deflistItem1Open'     : '<varlistentry><term>'              ,
830
+       'deflistItem1Close'    : '</term>'                           ,
831
+       'deflistItem2Open'     : '<listitem><para>'                  ,
832
+       'deflistItem2Close'    : '</para></listitem></varlistentry>' ,
833
+       # 'bar1'                 : '<>'                                , # Don't know
834
+       # 'bar2'                 : '<>'                                , # Don't know
835
+       'url'                  : '<ulink url="\a">\a</ulink>'        ,
836
+       'urlMark'              : '<ulink url="\a">\a</ulink>'        ,
837
+       'email'                : '<email>\a</email>'                 ,
838
+       'emailMark'            : '<email>\a</email>'                 ,
839
+       'img'                  : '<mediaobject><imageobject><imagedata fileref="\a"/></imageobject></mediaobject>',
840
+       # '_imgAlignLeft'        : ''                                 , # Don't know
841
+       # '_imgAlignCenter'      : ''                                 , # Don't know
842
+       # '_imgAlignRight'       : ''                                 , # Don't know
843
+       # 'tableOpen'            : '<informaltable><tgroup cols=""><tbody>', # Don't work, need to know number of cols
844
+       # 'tableClose'           : '</tbody></tgroup></informaltable>' ,
845
+       # 'tableRowOpen'         : '<row>'                             ,
846
+       # 'tableRowClose'        : '</row>'                            ,
847
+       # 'tableCellOpen'        : '<entry>'                           ,
848
+       # 'tableCellClose'       : '</entry>'                          ,
849
+       # 'tableTitleRowOpen'    : '<thead>'                           ,
850
+       # 'tableTitleRowClose'   : '</thead>'                          ,
851
+       # '_tableBorder'         : ' frame="all"'                      ,
852
+       # '_tableAlignCenter'    : ' align="center"'                   ,
853
+       # '_tableCellAlignRight' : ' align="right"'                    ,
854
+       # '_tableCellAlignCenter': ' align="center"'                   ,
855
+       # '_tableCellColSpan'    : ' COLSPAN="\a"'                     ,
856
+       'TOC'                  : '<index/>'                          ,
857
+       'comment'              : '<!-- \a -->'                       ,
858
+       'EOD'                  : '</article>'
859
+   },
860
+   
861
+   'tex': {
862
+       'title1'               : '~A~\section*{\a}'     ,
863
+       'title2'               : '~A~\\subsection*{\a}'   ,
864
+       'title3'               : '~A~\\subsubsection*{\a}',
865
+       # title 4/5: DIRTY: para+BF+\\+\n
866
+       'title4'               : '~A~\\paragraph{}\\textbf{\a}\\\\\n',
867
+       'title5'               : '~A~\\paragraph{}\\textbf{\a}\\\\\n',
868
+       'numtitle1'            : '\n~A~\section{\a}'      ,
869
+       'numtitle2'            : '~A~\\subsection{\a}'    ,
870
+       'numtitle3'            : '~A~\\subsubsection{\a}' ,
871
+       'anchor'               : '\\hypertarget{\a}{}\n'  ,
872
+       'blockVerbOpen'        : '\\begin{verbatim}'   ,
873
+       'blockVerbClose'       : '\\end{verbatim}'     ,
874
+       'blockQuoteOpen'       : '\\begin{quotation}'  ,
875
+       'blockQuoteClose'      : '\\end{quotation}'    ,
876
+       'fontMonoOpen'         : '\\texttt{'           ,
877
+       'fontMonoClose'        : '}'                   ,
878
+       'fontBoldOpen'         : '\\textbf{'           ,
879
+       'fontBoldClose'        : '}'                   ,
880
+       'fontItalicOpen'       : '\\textit{'           ,
881
+       'fontItalicClose'      : '}'                   ,
882
+       'fontUnderlineOpen'    : '\\underline{'        ,
883
+       'fontUnderlineClose'   : '}'                   ,
884
+       'fontStrikeOpen'       : '\\sout{'             ,
885
+       'fontStrikeClose'      : '}'                   ,
886
+       'listOpen'             : '\\begin{itemize}'    ,
887
+       'listClose'            : '\\end{itemize}'      ,
888
+       'listOpenCompact'      : '\\begin{compactitem}',
889
+       'listCloseCompact'     : '\\end{compactitem}'  ,
890
+       'listItemOpen'         : '\\item '             ,
891
+       'numlistOpen'          : '\\begin{enumerate}'  ,
892
+       'numlistClose'         : '\\end{enumerate}'    ,
893
+       'numlistOpenCompact'   : '\\begin{compactenum}',
894
+       'numlistCloseCompact'  : '\\end{compactenum}'  ,
895
+       'numlistItemOpen'      : '\\item '             ,
896
+       'deflistOpen'          : '\\begin{description}',
897
+       'deflistClose'         : '\\end{description}'  ,
898
+       'deflistOpenCompact'   : '\\begin{compactdesc}',
899
+       'deflistCloseCompact'  : '\\end{compactdesc}'  ,
900
+       'deflistItem1Open'     : '\\item['             ,
901
+       'deflistItem1Close'    : ']'                   ,
902
+       'bar1'                 : '\\hrulefill{}'       ,
903
+       'bar2'                 : '\\rule{\linewidth}{1mm}',
904
+       'url'                  : '\\htmladdnormallink{\a}{\a}',
905
+       'urlMark'              : '\\htmladdnormallink{\a}{\a}',
906
+       'email'                : '\\htmladdnormallink{\a}{mailto:\a}',
907
+       'emailMark'            : '\\htmladdnormallink{\a}{mailto:\a}',
908
+       'img'                  : '\\includegraphics{\a}',
909
+       'tableOpen'            : '\\begin{center}\\begin{tabular}{|~C~|}',
910
+       'tableClose'           : '\\end{tabular}\\end{center}',
911
+       'tableRowOpen'         : '\\hline ' ,
912
+       'tableRowClose'        : ' \\\\'    ,
913
+       'tableCellSep'         : ' & '      ,
914
+       '_tableColAlignLeft'   : 'l'        ,
915
+       '_tableColAlignRight'  : 'r'        ,
916
+       '_tableColAlignCenter' : 'c'        ,
917
+       '_tableCellAlignLeft'  : 'l'        ,
918
+       '_tableCellAlignRight' : 'r'        ,
919
+       '_tableCellAlignCenter': 'c'        ,
920
+       '_tableCellColSpan'    : '\a'       ,
921
+       '_tableCellMulticolOpen'  : '\\multicolumn{\a}{|~C~|}{',
922
+       '_tableCellMulticolClose' : '}',
923
+       'tableColAlignSep'     : '|'        ,
924
+       'comment'              : '% \a'     ,
925
+       'TOC'                  : '\\tableofcontents',
926
+       'pageBreak'            : '\\clearpage',
927
+       'EOD'                  : '\\end{document}'
928
+   },
929
+   
930
+   'lout': {
931
+       'paragraphOpen'        : '@LP'                     ,
932
+       'blockTitle1Open'      : '@BeginSections'          ,
933
+       'blockTitle1Close'     : '@EndSections'            ,
934
+       'blockTitle2Open'      : ' @BeginSubSections'      ,
935
+       'blockTitle2Close'     : ' @EndSubSections'        ,
936
+       'blockTitle3Open'      : '  @BeginSubSubSections'  ,
937
+       'blockTitle3Close'     : '  @EndSubSubSections'    ,
938
+       'title1Open'           : '~A~@Section @Title { \a } @Begin',
939
+       'title1Close'          : '@End @Section'           ,
940
+       'title2Open'           : '~A~ @SubSection @Title { \a } @Begin',
941
+       'title2Close'          : ' @End @SubSection'       ,
942
+       'title3Open'           : '~A~  @SubSubSection @Title { \a } @Begin',
943
+       'title3Close'          : '  @End @SubSubSection'   ,
944
+       'title4Open'           : '~A~@LP @LeftDisplay @B { \a }',
945
+       'title5Open'           : '~A~@LP @LeftDisplay @B { \a }',
946
+       'anchor'               : '@Tag { \a }\n'       ,
947
+       'blockVerbOpen'        : '@LP @ID @F @RawVerbatim @Begin',
948
+       'blockVerbClose'       : '@End @RawVerbatim'   ,
949
+       'blockQuoteOpen'       : '@QD {'               ,
950
+       'blockQuoteClose'      : '}'                   ,
951
+       # enclosed inside {} to deal with joined**words**
952
+       'fontMonoOpen'         : '{@F {'               ,
953
+       'fontMonoClose'        : '}}'                  ,
954
+       'fontBoldOpen'         : '{@B {'               ,
955
+       'fontBoldClose'        : '}}'                  ,
956
+       'fontItalicOpen'       : '{@II {'              ,
957
+       'fontItalicClose'      : '}}'                  ,
958
+       'fontUnderlineOpen'    : '{@Underline{'        ,
959
+       'fontUnderlineClose'   : '}}'                  ,
960
+       # the full form is more readable, but could be BL EL LI NL TL DTI
961
+       'listOpen'             : '@BulletList'         ,
962
+       'listClose'            : '@EndList'            ,
963
+       'listItemOpen'         : '@ListItem{'          ,
964
+       'listItemClose'        : '}'                   ,
965
+       'numlistOpen'          : '@NumberedList'       ,
966
+       'numlistClose'         : '@EndList'            ,
967
+       'numlistItemOpen'      : '@ListItem{'          ,
968
+       'numlistItemClose'     : '}'                   ,
969
+       'deflistOpen'          : '@TaggedList'         ,
970
+       'deflistClose'         : '@EndList'            ,
971
+       'deflistItem1Open'     : '@DropTagItem {'      ,
972
+       'deflistItem1Close'    : '}'                   ,
973
+       'deflistItem2Open'     : '{'                   ,
974
+       'deflistItem2Close'    : '}'                   ,
975
+       'bar1'                 : '@DP @FullWidthRule'  ,
976
+       'url'                  : '{blue @Colour { \a }}'      ,
977
+       'urlMark'              : '\a ({blue @Colour { \a }})' ,
978
+       'email'                : '{blue @Colour { \a }}'      ,
979
+       'emailMark'            : '\a ({blue Colour{ \a }})'   ,
980
+       'img'                  : '~A~@IncludeGraphic { \a }'  , # eps only!
981
+       '_imgAlignLeft'        : '@LeftDisplay '              ,
982
+       '_imgAlignRight'       : '@RightDisplay '             ,
983
+       '_imgAlignCenter'      : '@CentredDisplay '           ,
984
+       # lout tables are *way* complicated, no support for now
985
+       #'tableOpen'            : '~A~@Tbl~B~\naformat{ @Cell A | @Cell B } {',
986
+       #'tableClose'           : '}'     ,
987
+       #'tableRowOpen'         : '@Rowa\n'       ,
988
+       #'tableTitleRowOpen'    : '@HeaderRowa'       ,
989
+       #'tableCenterAlign'     : '@CentredDisplay '         ,
990
+       #'tableCellOpen'        : '\a {'                     ,  # A, B, ...
991
+       #'tableCellClose'       : '}'                        ,
992
+       #'_tableBorder'         : '\nrule {yes}'             ,
993
+       'comment'              : '# \a'                     ,
994
+       # @MakeContents must be on the config file
995
+       'TOC'                  : '@DP @ContentsGoesHere @DP',
996
+       'pageBreak'            : '@NP'                      ,
997
+       'EOD'                  : '@End @Text'
998
+   },
999
+   
1000
+   # http://moinmo.in/SyntaxReference
1001
+   'moin': {
1002
+       'title1'                : '= \a ='        ,
1003
+       'title2'                : '== \a =='      ,
1004
+       'title3'                : '=== \a ==='    ,
1005
+       'title4'                : '==== \a ===='  ,
1006
+       'title5'                : '===== \a =====',
1007
+       'blockVerbOpen'         : '{{{'           ,
1008
+       'blockVerbClose'        : '}}}'           ,
1009
+       'blockQuoteLine'        : '  '            ,
1010
+       'fontMonoOpen'          : '{{{'           ,
1011
+       'fontMonoClose'         : '}}}'           ,
1012
+       'fontBoldOpen'          : "'''"           ,
1013
+       'fontBoldClose'         : "'''"           ,
1014
+       'fontItalicOpen'        : "''"            ,
1015
+       'fontItalicClose'       : "''"            ,
1016
+       'fontUnderlineOpen'     : '__'            ,
1017
+       'fontUnderlineClose'    : '__'            ,
1018
+       'fontStrikeOpen'        : '--('           ,
1019
+       'fontStrikeClose'       : ')--'           ,
1020
+       'listItemOpen'          : ' * '           ,
1021
+       'numlistItemOpen'       : ' \a. '         ,
1022
+       'deflistItem1Open'      : ' '             ,
1023
+       'deflistItem1Close'     : '::'            ,
1024
+       'deflistItem2LinePrefix': ' :: '          ,
1025
+       'bar1'                  : '----'          ,
1026
+       'bar2'                  : '--------'      ,
1027
+       'url'                   : '[\a]'          ,
1028
+       'urlMark'               : '[\a \a]'       ,
1029
+       'email'                 : '[\a]'          ,
1030
+       'emailMark'             : '[\a \a]'       ,
1031
+       'img'                   : '[\a]'          ,
1032
+       'tableRowOpen'          : '||'            ,
1033
+       'tableCellOpen'         : '~A~'           ,
1034
+       'tableCellClose'        : '||'            ,
1035
+       'tableTitleCellClose'   : '||'            ,
1036
+       '_tableCellAlignRight'  : '<)>'           ,
1037
+       '_tableCellAlignCenter' : '<:>'           ,
1038
+       'comment'               : '/* \a */'      ,
1039
+       'TOC'                   : '[[TableOfContents]]'
1040
+   },
1041
+
1042
+   # http://code.google.com/p/support/wiki/WikiSyntax
1043
+   'gwiki': {
1044
+       'title1'               : '= \a ='        ,
1045
+       'title2'               : '== \a =='      ,
1046
+       'title3'               : '=== \a ==='    ,
1047
+       'title4'               : '==== \a ===='  ,
1048
+       'title5'               : '===== \a =====',
1049
+       'blockVerbOpen'        : '{{{'           ,
1050
+       'blockVerbClose'       : '}}}'           ,
1051
+       'blockQuoteLine'       : '  '            ,
1052
+       'fontMonoOpen'         : '{{{'           ,
1053
+       'fontMonoClose'        : '}}}'           ,
1054
+       'fontBoldOpen'         : '*'             ,
1055
+       'fontBoldClose'        : '*'             ,
1056
+       'fontItalicOpen'       : '_'             , # underline == italic
1057
+       'fontItalicClose'      : '_'             ,
1058
+       'fontStrikeOpen'       : '~~'            ,
1059
+       'fontStrikeClose'      : '~~'            ,
1060
+       'listItemOpen'         : ' * '           ,
1061
+       'numlistItemOpen'      : ' # '           ,
1062
+       'url'                  : '\a'            ,
1063
+       'urlMark'              : '[\a \a]'       ,
1064
+       'email'                : 'mailto:\a'     ,
1065
+       'emailMark'            : '[mailto:\a \a]',
1066
+       'img'                  : '[\a]'          ,
1067
+       'tableRowOpen'         : '|| '           ,
1068
+       'tableRowClose'        : ' ||'           ,
1069
+       'tableCellSep'         : ' || '          ,
1070
+   },
1071
+
1072
+   # http://powerman.name/doc/asciidoc
1073
+   'adoc': {
1074
+       'title1'               : '== \a'         ,
1075
+       'title2'               : '=== \a'        ,
1076
+       'title3'               : '==== \a'       ,
1077
+       'title4'               : '===== \a'      ,
1078
+       'title5'               : '===== \a'      ,
1079
+       'blockVerbOpen'        : '----'          ,
1080
+       'blockVerbClose'       : '----'          ,
1081
+       'fontMonoOpen'         : '+'             ,
1082
+       'fontMonoClose'        : '+'             ,
1083
+       'fontBoldOpen'         : '*'             ,
1084
+       'fontBoldClose'        : '*'             ,
1085
+       'fontItalicOpen'       : '_'             ,
1086
+       'fontItalicClose'      : '_'             ,
1087
+       'listItemOpen'         : '- '            ,
1088
+       'listItemLine'         : '\t'            ,
1089
+       'numlistItemOpen'      : '. '            ,
1090
+       'url'                  : '\a'            ,
1091
+       'urlMark'              : '\a[\a]'        ,
1092
+       'email'                : 'mailto:\a'     ,
1093
+       'emailMark'            : 'mailto:\a[\a]' ,
1094
+       'img'                  : 'image::\a[]'   ,
1095
+   },
1096
+
1097
+   # http://wiki.splitbrain.org/wiki:syntax
1098
+   # Hint: <br> is \\ $
1099
+   # Hint: You can add footnotes ((This is a footnote))
1100
+   'doku': {
1101
+       'title1'               : '===== \a =====',
1102
+       'title2'               : '==== \a ===='  ,
1103
+       'title3'               : '=== \a ==='    ,
1104
+       'title4'               : '== \a =='      ,
1105
+       'title5'               : '= \a ='        ,
1106
+       # DokuWiki uses '  ' identation to mark verb blocks (see indentverbblock)
1107
+       'blockQuoteLine'       : '>'             ,
1108
+       'fontMonoOpen'         : "''"            ,
1109
+       'fontMonoClose'        : "''"            ,
1110
+       'fontBoldOpen'         : "**"            ,
1111
+       'fontBoldClose'        : "**"            ,
1112
+       'fontItalicOpen'       : "//"            ,
1113
+       'fontItalicClose'      : "//"            ,
1114
+       'fontUnderlineOpen'    : "__"            ,
1115
+       'fontUnderlineClose'   : "__"            ,
1116
+       'fontStrikeOpen'       : '<del>'         ,
1117
+       'fontStrikeClose'      : '</del>'        ,
1118
+       'listItemOpen'         : '  * '          ,
1119
+       'numlistItemOpen'      : '  - '          ,
1120
+       'bar1'                 : '----'          ,
1121
+       'url'                  : '[[\a]]'        ,
1122
+       'urlMark'              : '[[\a|\a]]'     ,
1123
+       'email'                : '[[\a]]'        ,
1124
+       'emailMark'            : '[[\a|\a]]'     ,
1125
+       'img'                  : '{{\a}}'        ,
1126
+       'imgAlignLeft'         : '{{\a }}'       ,
1127
+       'imgAlignRight'        : '{{ \a}}'       ,
1128
+       'imgAlignCenter'       : '{{ \a }}'      ,
1129
+       'tableTitleRowOpen'    : '^ '            ,
1130
+       'tableTitleRowClose'   : ' ^'            ,
1131
+       'tableTitleCellSep'    : ' ^ '           ,
1132
+       'tableRowOpen'         : '| '            ,
1133
+       'tableRowClose'        : ' |'            ,
1134
+       'tableCellSep'         : ' | '           ,
1135
+       # DokuWiki has no attributes. The content must be aligned!
1136
+       # '_tableCellAlignRight' : '<)>'           , # ??
1137
+       # '_tableCellAlignCenter': '<:>'           , # ??
1138
+       # DokuWiki colspan is the same as txt2tags' with multiple |||
1139
+       # 'comment'             : '## \a'         , # ??
1140
+       # TOC is automatic
1141
+   },
1142
+   
1143
+   # http://www.pmwiki.org/wiki/PmWiki/TextFormattingRules
1144
+   'pmw': {
1145
+       'title1'               : '~A~! \a '      ,
1146
+       'title2'               : '~A~!! \a '     ,
1147
+       'title3'               : '~A~!!! \a '    ,
1148
+       'title4'               : '~A~!!!! \a '   ,
1149
+       'title5'               : '~A~!!!!! \a '  ,
1150
+       'blockQuoteOpen'       : '->'            ,
1151
+       'blockQuoteClose'      : '\n'            ,
1152
+       # In-text font
1153
+       'fontLargeOpen'        : "[+"            ,
1154
+       'fontLargeClose'       : "+]"            ,
1155
+       'fontLargerOpen'       : "[++"           ,
1156
+       'fontLargerClose'      : "++]"           ,
1157
+       'fontSmallOpen'        : "[-"            ,
1158
+       'fontSmallClose'       : "-]"            ,
1159
+       'fontLargerOpen'       : "[--"           ,
1160
+       'fontLargerClose'      : "--]"           ,
1161
+       'fontMonoOpen'         : "@@"            ,
1162
+       'fontMonoClose'        : "@@"            ,
1163
+       'fontBoldOpen'         : "'''"           ,
1164
+       'fontBoldClose'        : "'''"           ,
1165
+       'fontItalicOpen'       : "''"            ,
1166
+       'fontItalicClose'      : "''"            ,
1167
+       'fontUnderlineOpen'    : "{+"            ,
1168
+       'fontUnderlineClose'   : "+}"            ,
1169
+       'fontStrikeOpen'       : '{-'            ,
1170
+       'fontStrikeClose'      : '-}'            ,
1171
+       # Lists
1172
+       'listItemLine'          : '*'            ,
1173
+       'numlistItemLine'       : '#'            ,
1174
+       'deflistItem1Open'      : ': '           ,
1175
+       'deflistItem1Close'     : ':'            ,
1176
+       'deflistItem2LineOpen'  : '::'           ,
1177
+       'deflistItem2LineClose' : ':'            ,
1178
+       # Verbatim block
1179
+       'blockVerbOpen'        : '[@'            ,
1180
+       'blockVerbClose'       : '@]'            ,
1181
+       'bar1'                 : '----'          ,
1182
+       # URL, email and anchor
1183
+       'url'                   : '\a'           ,
1184
+       'urlMark'               : '[[\a -> \a]]' ,
1185
+       'email'                 : '\a'           ,
1186
+       'emailMark'             : '[[\a -> mailto:\a]]',
1187
+       'anchor'                : '[[#\a]]\n'    ,
1188
+       # Image markup
1189
+       'img'                   : '\a'           ,
1190
+       #'imgAlignLeft'         : '{{\a }}'       ,
1191
+       #'imgAlignRight'        : '{{ \a}}'       ,
1192
+       #'imgAlignCenter'       : '{{ \a }}'      ,
1193
+       # Table attributes
1194
+       'tableTitleRowOpen'    : '||! '          ,
1195
+       'tableTitleRowClose'   : '||'            ,
1196
+       'tableTitleCellSep'    : ' ||!'          ,
1197
+       'tableRowOpen'         : '||'            ,
1198
+       'tableRowClose'        : '||'            ,
1199
+       'tableCellSep'         : ' ||'           ,
1200
+   },
1201
+   
1202
+   # http://en.wikipedia.org/wiki/Help:Editing
1203
+   'wiki': {
1204
+       'title1'                : '== \a =='        ,
1205
+       'title2'                : '=== \a ==='      ,
1206
+       'title3'                : '==== \a ===='    ,
1207
+       'title4'                : '===== \a ====='  ,
1208
+       'title5'                : '====== \a ======',
1209
+       'blockVerbOpen'         : '<pre>'           ,
1210
+       'blockVerbClose'        : '</pre>'          ,
1211
+       'blockQuoteOpen'        : '<blockquote>'    ,
1212
+       'blockQuoteClose'       : '</blockquote>'   ,
1213
+       'fontMonoOpen'          : '<tt>'            ,
1214
+       'fontMonoClose'         : '</tt>'           ,
1215
+       'fontBoldOpen'          : "'''"             ,
1216
+       'fontBoldClose'         : "'''"             ,
1217
+       'fontItalicOpen'        : "''"              ,
1218
+       'fontItalicClose'       : "''"              ,
1219
+       'fontUnderlineOpen'     : '<u>'             ,
1220
+       'fontUnderlineClose'    : '</u>'            ,
1221
+       'fontStrikeOpen'        : '<s>'             ,
1222
+       'fontStrikeClose'       : '</s>'            ,
1223
+       #XXX Mixed lists not working: *#* list inside numlist inside list
1224
+       'listItemLine'          : '*'               ,
1225
+       'numlistItemLine'       : '#'               ,
1226
+       'deflistItem1Open'      : '; '              ,
1227
+       'deflistItem2LinePrefix': ': '            ,
1228
+       'bar1'                  : '----'            ,
1229
+       'url'                   : '[\a]'            ,
1230
+       'urlMark'               : '[\a \a]'         ,
1231
+       'email'                 : 'mailto:\a'       ,
1232
+       'emailMark'             : '[mailto:\a \a]'  ,
1233
+       # [[Image:foo.png|right|Optional alt/caption text]] (right, left, center, none)
1234
+       'img'                   : '[[Image:\a~A~]]' ,
1235
+       '_imgAlignLeft'         : '|left'           ,
1236
+       '_imgAlignCenter'       : '|center'         ,
1237
+       '_imgAlignRight'        : '|right'          ,
1238
+       # {| border="1" cellspacing="0" cellpadding="4" align="center"
1239
+       'tableOpen'             : '{|~A~~B~ cellpadding="4"',
1240
+       'tableClose'            : '|}'              ,
1241
+       'tableRowOpen'          : '|-\n| '          ,
1242
+       'tableTitleRowOpen'     : '|-\n! '          ,
1243
+       'tableCellSep'          : ' || '            ,
1244
+       'tableTitleCellSep'     : ' !! '            ,
1245
+       '_tableBorder'          : ' border="1"'     ,
1246
+       '_tableAlignCenter'     : ' align="center"' ,
1247
+       'comment'               : '<!-- \a -->'     ,
1248
+       'TOC'                   : '__TOC__'         ,
1249
+   },
1250
+   
1251
+   # http://www.inference.phy.cam.ac.uk/mackay/mgp/SYNTAX
1252
+   # http://en.wikipedia.org/wiki/MagicPoint
1253
+   'mgp': {
1254
+       'paragraphOpen'         : '%font "normal", size 5'     ,
1255
+       'title1'                : '%page\n\n\a\n'              ,
1256
+       'title2'                : '%page\n\n\a\n'              ,
1257
+       'title3'                : '%page\n\n\a\n'              ,
1258
+       'title4'                : '%page\n\n\a\n'              ,
1259
+       'title5'                : '%page\n\n\a\n'              ,
1260
+       'blockVerbOpen'         : '%font "mono"'               ,
1261
+       'blockVerbClose'        : '%font "normal"'             ,
1262
+       'blockQuoteOpen'        : '%prefix "       "'          ,
1263
+       'blockQuoteClose'       : '%prefix "  "'               ,
1264
+       'fontMonoOpen'          : '\n%cont, font "mono"\n'     ,
1265
+       'fontMonoClose'         : '\n%cont, font "normal"\n'   ,
1266
+       'fontBoldOpen'          : '\n%cont, font "normal-b"\n' ,
1267
+       'fontBoldClose'         : '\n%cont, font "normal"\n'   ,
1268
+       'fontItalicOpen'        : '\n%cont, font "normal-i"\n' ,
1269
+       'fontItalicClose'       : '\n%cont, font "normal"\n'   ,
1270
+       'fontUnderlineOpen'     : '\n%cont, fore "cyan"\n'     ,
1271
+       'fontUnderlineClose'    : '\n%cont, fore "white"\n'    ,
1272
+       'listItemLine'          : '\t'                         ,
1273
+       'numlistItemLine'       : '\t'                         ,
1274
+       'numlistItemOpen'       : '\a. '                       ,
1275
+       'deflistItem1Open'      : '\t\n%cont, font "normal-b"\n',
1276
+       'deflistItem1Close'     : '\n%cont, font "normal"\n'   ,
1277
+       'bar1'                  : '%bar "white" 5'             ,
1278
+       'bar2'                  : '%pause'                     ,
1279
+       'url'                   : '\n%cont, fore "cyan"\n\a'   +\
1280
+                                 '\n%cont, fore "white"\n'    ,
1281
+       'urlMark'               : '\a \n%cont, fore "cyan"\n\a'+\
1282
+                                 '\n%cont, fore "white"\n'    ,
1283
+       'email'                 : '\n%cont, fore "cyan"\n\a'   +\
1284
+                                 '\n%cont, fore "white"\n'    ,
1285
+       'emailMark'             : '\a \n%cont, fore "cyan"\n\a'+\
1286
+                                 '\n%cont, fore "white"\n'    ,
1287
+       'img'                   : '~A~\n%newimage "\a"\n%left\n',
1288
+       '_imgAlignLeft'         : '\n%left'                    ,
1289
+       '_imgAlignRight'        : '\n%right'                   ,
1290
+       '_imgAlignCenter'       : '\n%center'                  ,
1291
+       'comment'               : '%% \a'                      ,
1292
+       'pageBreak'             : '%page\n\n\n'                ,
1293
+       'EOD'                   : '%%EOD'
1294
+   },
1295
+   
1296
+   # man groff_man ; man 7 groff
1297
+   'man': {
1298
+       'paragraphOpen'         : '.P'     ,
1299
+       'title1'                : '.SH \a' ,
1300
+       'title2'                : '.SS \a' ,
1301
+       'title3'                : '.SS \a' ,
1302
+       'title4'                : '.SS \a' ,
1303
+       'title5'                : '.SS \a' ,
1304
+       'blockVerbOpen'         : '.nf'    ,
1305
+       'blockVerbClose'        : '.fi\n'  ,
1306
+       'blockQuoteOpen'        : '.RS'    ,
1307
+       'blockQuoteClose'       : '.RE'    ,
1308
+       'fontBoldOpen'          : '\\fB'   ,
1309
+       'fontBoldClose'         : '\\fR'   ,
1310
+       'fontItalicOpen'        : '\\fI'   ,
1311
+       'fontItalicClose'       : '\\fR'   ,
1312
+       'listOpen'              : '.RS'    ,
1313
+       'listItemOpen'          : '.IP \(bu 3\n',
1314
+       'listClose'             : '.RE'    ,
1315
+       'numlistOpen'           : '.RS'    ,
1316
+       'numlistItemOpen'       : '.IP \a. 3\n',
1317
+       'numlistClose'          : '.RE'    ,
1318
+       'deflistItem1Open'      : '.TP\n'  ,
1319
+       'bar1'                  : '\n\n'   ,
1320
+       'url'                   : '\a'     ,
1321
+       'urlMark'               : '\a (\a)',
1322
+       'email'                 : '\a'     ,
1323
+       'emailMark'             : '\a (\a)',
1324
+       'img'                   : '\a'     ,
1325
+       'tableOpen'             : '.TS\n~A~~B~tab(^); ~C~.',
1326
+       'tableClose'            : '.TE'     ,
1327
+       'tableRowOpen'          : ' '       ,
1328
+       'tableCellSep'          : '^'       ,
1329
+       '_tableAlignCenter'     : 'center, ',
1330
+       '_tableBorder'          : 'allbox, ',
1331
+       '_tableColAlignLeft'    : 'l'       ,
1332
+       '_tableColAlignRight'   : 'r'       ,
1333
+       '_tableColAlignCenter'  : 'c'       ,
1334
+       'comment'               : '.\\" \a'
1335
+   },
1336
+   
1337
+   'pm6': {
1338
+       'paragraphOpen'         : '<@Normal:>'    ,
1339
+       'title1'                : '<@Title1:>\a',
1340
+       'title2'                : '<@Title2:>\a',
1341
+       'title3'                : '<@Title3:>\a',
1342
+       'title4'                : '<@Title4:>\a',
1343
+       'title5'                : '<@Title5:>\a',
1344
+       'blockVerbOpen'         : '<@PreFormat:>' ,
1345
+       'blockQuoteLine'        : '<@Quote:>'     ,
1346
+       'fontMonoOpen'          : '<FONT "Lucida Console"><SIZE 9>' ,
1347
+       'fontMonoClose'         : '<SIZE$><FONT$>',
1348
+       'fontBoldOpen'          : '<B>'           ,
1349
+       'fontBoldClose'         : '<P>'           ,
1350
+       'fontItalicOpen'        : '<I>'           ,
1351
+       'fontItalicClose'       : '<P>'           ,
1352
+       'fontUnderlineOpen'     : '<U>'           ,
1353
+       'fontUnderlineClose'    : '<P>'           ,
1354
+       'listOpen'              : '<@Bullet:>'    ,
1355
+       'listItemOpen'          : '*\t'           ,  # \x95 == ~U -> changed to "*"
1356
+       'numlistOpen'           : '<@Bullet:>'    ,
1357
+       'numlistItemOpen'       : '*\t'           ,
1358
+       'bar1'                  : '\a'            ,
1359
+       'url'                   : '<U>\a<P>'      ,  # underline
1360
+       'urlMark'               : '\a <U>\a<P>'   ,
1361
+       'email'                 : '\a'            ,
1362
+       'emailMark'             : '\a \a'         ,
1363
+       'img'                   : '\a'
1364
+   },
1365
+   # http://www.wikicreole.org/wiki/AllMarkup
1366
+   'creole': {
1367
+       'title1'               : '= \a ='        ,
1368
+       'title2'               : '== \a =='      ,
1369
+       'title3'               : '=== \a ==='    ,
1370
+       'title4'               : '==== \a ===='  ,
1371
+       'title5'               : '===== \a =====',
1372
+       'blockVerbOpen'        : '{{{'           ,
1373
+       'blockVerbClose'       : '}}}'           ,
1374
+       'blockQuoteLine'       : '  '            ,
1375
+   #   'fontMonoOpen'         : '##'            ,  # planned for 2.0,
1376
+   #   'fontMonoClose'        : '##'            ,  # meanwhile we disable it
1377
+       'fontBoldOpen'         : '**'            ,
1378
+       'fontBoldClose'        : '**'            ,
1379
+       'fontItalicOpen'       : '//'            ,
1380
+       'fontItalicClose'      : '//'            ,
1381
+       'fontUnderlineOpen'    : '//'            ,  # no underline in 1.0, planned for 2.0,
1382
+       'fontUnderlineClose'   : '//'            ,  # meanwhile we can use italic (emphasized)
1383
+   #   'fontStrikeOpen'       : '--'            ,  # planned for 2.0,
1384
+   #   'fontStrikeClose'      : '--'            ,  # meanwhile we disable it
1385
+       'listItemLine'          : '*'            ,
1386
+       'numlistItemLine'       : '#'            ,
1387
+       'deflistItem2LinePrefix': ':'            ,
1388
+       'bar1'                  : '----'         ,
1389
+       'url'                  : '[[\a]]'        ,
1390
+       'urlMark'              : '[[\a|\a]]'     ,
1391
+       'img'                  : '{{\a}}'        ,
1392
+       'tableTitleRowOpen'    : '|= '           ,
1393
+       'tableTitleRowClose'   : '|'             ,
1394
+       'tableTitleCellSep'    : ' |= '          ,
1395
+       'tableRowOpen'         : '| '            ,
1396
+       'tableRowClose'        : ' |'            ,
1397
+       'tableCellSep'         : ' | '           ,
1398
+       # TODO: placeholder (mark for unknown syntax)
1399
+       # if possible: http://www.wikicreole.org/wiki/Placeholder
1400
+   }
1401
+   }
1402
+   
1403
+   # Exceptions for --css-sugar
1404
+   if config['css-sugar'] and config['target'] in ('html','xhtml'):
1405
+       # Change just HTML because XHTML inherits it
1406
+       htmltags = alltags['html']
1407
+       # Table with no cellpadding
1408
+       htmltags['tableOpen'] = htmltags['tableOpen'].replace(' CELLPADDING="4"', '')
1409
+       # DIVs
1410
+       htmltags['tocOpen' ] = '<DIV CLASS="toc">'
1411
+       htmltags['tocClose'] = '</DIV>'
1412
+       htmltags['bodyOpen'] = '<DIV CLASS="body" ID="body">'
1413
+       htmltags['bodyClose']= '</DIV>'
1414
+   
1415
+   # Make the HTML -> XHTML inheritance
1416
+   xhtml = alltags['html'].copy()
1417
+   for key in xhtml.keys(): xhtml[key] = xhtml[key].lower()
1418
+   # Some like HTML tags as lowercase, some don't... (headers out)
1419
+   if HTML_LOWER: alltags['html'] = xhtml.copy()
1420
+   xhtml.update(alltags['xhtml'])
1421
+   alltags['xhtml'] = xhtml.copy()
1422
+
1423
+   # Compose the target tags dictionary
1424
+   tags = {}
1425
+   target_tags = alltags[config['target']].copy()
1426
+   
1427
+   for key in keys: tags[key] = '' # create empty keys
1428
+   for key in target_tags.keys():
1429
+       tags[key] = maskEscapeChar(target_tags[key]) # populate
1430
+
1431
+   # Map strong line to pagebreak
1432
+   if rules['mapbar2pagebreak'] and tags['pageBreak']:
1433
+       tags['bar2'] = tags['pageBreak']
1434
+
1435
+   # Map strong line to separator if not defined
1436
+   if not tags['bar2'] and tags['bar1']:
1437
+       tags['bar2'] = tags['bar1']
1438
+
1439
+   return tags
1440
+
1441
+
1442
+##############################################################################
1443
+
1444
+
1445
+def getRules(config):
1446
+   "Returns all the target-specific syntax rules"
1447
+   
1448
+   ret = {}
1449
+   allrules = [
1450
+   
1451
+       # target rules (ON/OFF)
1452
+       'linkable',             # target supports external links
1453
+       'tableable',            # target supports tables
1454
+       'imglinkable',          # target supports images as links
1455
+       'imgalignable',         # target supports image alignment
1456
+       'imgasdefterm',         # target supports image as definition term
1457
+       'autonumberlist',       # target supports numbered lists natively
1458
+       'autonumbertitle',      # target supports numbered titles natively
1459
+       'stylable',             # target supports external style files
1460
+       'parainsidelist',       # lists items supports paragraph
1461
+       'compactlist',          # separate enclosing tags for compact lists
1462
+       'spacedlistitem',       # lists support blank lines between items
1463
+       'listnotnested',        # lists cannot be nested
1464
+       'quotenotnested',       # quotes cannot be nested
1465
+       'verbblocknotescaped',  # don't escape specials in verb block
1466
+       'verbblockfinalescape', # do final escapes in verb block
1467
+       'escapeurl',            # escape special in link URL
1468
+       'labelbeforelink',      # label comes before the link on the tag
1469
+       'onelinepara',          # dump paragraph as a single long line
1470
+       'tabletitlerowinbold',  # manually bold any cell on table titles
1471
+       'tablecellstrip',       # strip extra spaces from each table cell
1472
+       'tablecellspannable',   # the table cells can have span attribute
1473
+       'tablecellmulticol',    # separate open+close tags for multicol cells
1474
+       'barinsidequote',       # bars are allowed inside quote blocks
1475
+       'finalescapetitle',     # perform final escapes on title lines
1476
+       'autotocnewpagebefore', # break page before automatic TOC
1477
+       'autotocnewpageafter',  # break page after automatic TOC
1478
+       'autotocwithbars',      # automatic TOC surrounded by bars
1479
+       'mapbar2pagebreak',     # map the strong bar to a page break
1480
+       'titleblocks',          # titles must be on open/close section blocks
1481
+   
1482
+       # Target code beautify (ON/OFF)
1483
+       'indentverbblock',      # add leading spaces to verb block lines
1484
+       'breaktablecell',       # break lines after any table cell
1485
+       'breaktablelineopen',   # break line after opening table line
1486
+       'notbreaklistopen',     # don't break line after opening a new list
1487
+       'keepquoteindent',      # don't remove the leading TABs on quotes
1488
+       'keeplistindent',       # don't remove the leading spaces on lists
1489
+       'blankendautotoc',      # append a blank line at the auto TOC end
1490
+       'tagnotindentable',     # tags must be placed at the line beginning
1491
+       'spacedlistitemopen',   # append a space after the list item open tag
1492
+       'spacednumlistitemopen',# append a space after the numlist item open tag
1493
+       'deflisttextstrip',     # strip the contents of the deflist text
1494
+       'blanksaroundpara',     # put a blank line before and after paragraphs
1495
+       'blanksaroundverb',     # put a blank line before and after verb blocks
1496
+       'blanksaroundquote',    # put a blank line before and after quotes
1497
+       'blanksaroundlist',     # put a blank line before and after lists
1498
+       'blanksaroundnumlist',  # put a blank line before and after numlists
1499
+       'blanksarounddeflist',  # put a blank line before and after deflists
1500
+       'blanksaroundtable',    # put a blank line before and after tables
1501
+       'blanksaroundbar',      # put a blank line before and after bars
1502
+       'blanksaroundtitle',    # put a blank line before and after titles
1503
+       'blanksaroundnumtitle', # put a blank line before and after numtitles
1504
+   
1505
+       # Value settings
1506
+       'listmaxdepth',         # maximum depth for lists
1507
+       'quotemaxdepth',        # maximum depth for quotes
1508
+       'tablecellaligntype',   # type of table cell align: cell, column
1509
+   ]
1510
+   
1511
+   rules_bank = {
1512
+       'txt': {
1513
+           'indentverbblock':1,
1514
+           'spacedlistitem':1,
1515
+           'parainsidelist':1,
1516
+           'keeplistindent':1,
1517
+           'barinsidequote':1,
1518
+           'autotocwithbars':1,
1519
+
1520
+           'blanksaroundpara':1,
1521
+           'blanksaroundverb':1,
1522
+           'blanksaroundquote':1,
1523
+           'blanksaroundlist':1,
1524
+           'blanksaroundnumlist':1,
1525
+           'blanksarounddeflist':1,
1526
+           'blanksaroundtable':1,
1527
+           'blanksaroundbar':1,
1528
+           'blanksaroundtitle':1,
1529
+           'blanksaroundnumtitle':1,
1530
+       },
1531
+       'art': {
1532
+           #TIP art inherits all TXT rules
1533
+       },
1534
+       'html': {
1535
+           'indentverbblock':1,
1536
+           'linkable':1,
1537
+           'stylable':1,
1538
+           'escapeurl':1,
1539
+           'imglinkable':1,
1540
+           'imgalignable':1,
1541
+           'imgasdefterm':1,
1542
+           'autonumberlist':1,
1543
+           'spacedlistitem':1,
1544
+           'parainsidelist':1,
1545
+           'tableable':1,
1546
+           'tablecellstrip':1,
1547
+           'breaktablecell':1,
1548
+           'breaktablelineopen':1,
1549
+           'keeplistindent':1,
1550
+           'keepquoteindent':1,
1551
+           'barinsidequote':1,
1552
+           'autotocwithbars':1,
1553
+           'tablecellspannable':1,
1554
+           'tablecellaligntype':'cell',
1555
+
1556
+           # 'blanksaroundpara':1,
1557
+           'blanksaroundverb':1,
1558
+           # 'blanksaroundquote':1,
1559
+           'blanksaroundlist':1,
1560
+           'blanksaroundnumlist':1,
1561
+           'blanksarounddeflist':1,
1562
+           'blanksaroundtable':1,
1563
+           'blanksaroundbar':1,
1564
+           'blanksaroundtitle':1,
1565
+           'blanksaroundnumtitle':1,
1566
+       },
1567
+       'xhtml': {
1568
+           #TIP xhtml inherits all HTML rules
1569
+       },
1570
+       'sgml': {
1571
+           'linkable':1,
1572
+           'escapeurl':1,
1573
+           'autonumberlist':1,
1574
+           'spacedlistitem':1,
1575
+           'tableable':1,
1576
+           'tablecellstrip':1,
1577
+           'blankendautotoc':1,
1578
+           'quotenotnested':1,
1579
+           'keeplistindent':1,
1580
+           'keepquoteindent':1,
1581
+           'barinsidequote':1,
1582
+           'finalescapetitle':1,
1583
+           'tablecellaligntype':'column',
1584
+
1585
+           'blanksaroundpara':1,
1586
+           'blanksaroundverb':1,
1587
+           'blanksaroundquote':1,
1588
+           'blanksaroundlist':1,
1589
+           'blanksaroundnumlist':1,
1590
+           'blanksarounddeflist':1,
1591
+           'blanksaroundtable':1,
1592
+           'blanksaroundbar':1,
1593
+           'blanksaroundtitle':1,
1594
+           'blanksaroundnumtitle':1,
1595
+       },
1596
+       'dbk': {
1597
+           'linkable':1,
1598
+           'tableable':0, # activate when table tags are ready
1599
+           'imglinkable':1,
1600
+           'imgalignable':1,
1601
+           'imgasdefterm':1,
1602
+           'autonumberlist':1,
1603
+           'autonumbertitle':1,
1604
+           'parainsidelist':1,
1605
+           'spacedlistitem':1,
1606
+           'titleblocks':1,
1607
+       },
1608
+       'mgp': {
1609
+           'tagnotindentable':1,
1610
+           'spacedlistitem':1,
1611
+           'imgalignable':1,
1612
+           'autotocnewpagebefore':1,
1613
+
1614
+           'blanksaroundpara':1,
1615
+           'blanksaroundverb':1,
1616
+           # 'blanksaroundquote':1,
1617
+           'blanksaroundlist':1,
1618
+           'blanksaroundnumlist':1,
1619
+           'blanksarounddeflist':1,
1620
+           'blanksaroundtable':1,
1621
+           'blanksaroundbar':1,
1622
+           # 'blanksaroundtitle':1,
1623
+           # 'blanksaroundnumtitle':1,
1624
+       },
1625
+       'tex': {
1626
+           'stylable':1,
1627
+           'escapeurl':1,
1628
+           'autonumberlist':1,
1629
+           'autonumbertitle':1,
1630
+           'spacedlistitem':1,
1631
+           'compactlist':1,
1632
+           'parainsidelist':1,
1633
+           'tableable':1,
1634
+           'tablecellstrip':1,
1635
+           'tabletitlerowinbold':1,
1636
+           'verbblocknotescaped':1,
1637
+           'keeplistindent':1,
1638
+           'listmaxdepth':4,  # deflist is 6
1639
+           'quotemaxdepth':6,
1640
+           'barinsidequote':1,
1641
+           'finalescapetitle':1,
1642
+           'autotocnewpageafter':1,
1643
+           'mapbar2pagebreak':1,
1644
+           'tablecellaligntype':'column',
1645
+           'tablecellmulticol':1,
1646
+
1647
+           'blanksaroundpara':1,
1648
+           'blanksaroundverb':1,
1649
+           # 'blanksaroundquote':1,
1650
+           'blanksaroundlist':1,
1651
+           'blanksaroundnumlist':1,
1652
+           'blanksarounddeflist':1,
1653
+           'blanksaroundtable':1,
1654
+           'blanksaroundbar':1,
1655
+           'blanksaroundtitle':1,
1656
+           'blanksaroundnumtitle':1,
1657
+       },
1658
+       'lout': {
1659
+           'keepquoteindent':1,
1660
+           'deflisttextstrip':1,
1661
+           'escapeurl':1,
1662
+           'verbblocknotescaped':1,
1663
+           'imgalignable':1,
1664
+           'mapbar2pagebreak':1,
1665
+           'titleblocks':1,
1666
+           'autonumberlist':1,
1667
+           'parainsidelist':1,
1668
+
1669
+           'blanksaroundpara':1,
1670
+           'blanksaroundverb':1,
1671
+           # 'blanksaroundquote':1,
1672
+           'blanksaroundlist':1,
1673
+           'blanksaroundnumlist':1,
1674
+           'blanksarounddeflist':1,
1675
+           'blanksaroundtable':1,
1676
+           'blanksaroundbar':1,
1677
+           'blanksaroundtitle':1,
1678
+           'blanksaroundnumtitle':1,
1679
+       },
1680
+       'moin': {
1681
+           'spacedlistitem':1,
1682
+           'linkable':1,
1683
+           'keeplistindent':1,
1684
+           'tableable':1,
1685
+           'barinsidequote':1,
1686
+           'tabletitlerowinbold':1,
1687
+           'tablecellstrip':1,
1688
+           'autotocwithbars':1,
1689
+           'tablecellaligntype':'cell',
1690
+           'deflisttextstrip':1,
1691
+
1692
+           'blanksaroundpara':1,
1693
+           'blanksaroundverb':1,
1694
+           # 'blanksaroundquote':1,
1695
+           'blanksaroundlist':1,
1696
+           'blanksaroundnumlist':1,
1697
+           'blanksarounddeflist':1,
1698
+           'blanksaroundtable':1,
1699
+           # 'blanksaroundbar':1,
1700
+           'blanksaroundtitle':1,
1701
+           'blanksaroundnumtitle':1,
1702
+       },
1703
+       'gwiki': {
1704
+           'spacedlistitem':1,
1705
+           'linkable':1,
1706
+           'keeplistindent':1,
1707
+           'tableable':1,
1708
+           'tabletitlerowinbold':1,
1709
+           'tablecellstrip':1,
1710
+           'autonumberlist':1,
1711
+
1712
+           'blanksaroundpara':1,
1713
+           'blanksaroundverb':1,
1714
+           # 'blanksaroundquote':1,
1715
+           'blanksaroundlist':1,
1716
+           'blanksaroundnumlist':1,
1717
+           'blanksarounddeflist':1,
1718
+           'blanksaroundtable':1,
1719
+           # 'blanksaroundbar':1,
1720
+           'blanksaroundtitle':1,
1721
+           'blanksaroundnumtitle':1,
1722
+       },
1723
+       'adoc': {
1724
+           'spacedlistitem':1,
1725
+           'linkable':1,
1726
+           'keeplistindent':1,
1727
+           'autonumberlist':1,
1728
+           'autonumbertitle':1,
1729
+           'listnotnested':1,
1730
+           'blanksaroundpara':1,
1731
+           'blanksaroundverb':1,
1732
+           'blanksaroundlist':1,
1733
+           'blanksaroundnumlist':1,
1734
+           'blanksarounddeflist':1,
1735
+           'blanksaroundtable':1,
1736
+           'blanksaroundtitle':1,
1737
+           'blanksaroundnumtitle':1,
1738
+       },
1739
+       'doku': {
1740
+           'indentverbblock':1, # DokuWiki uses '  ' to mark verb blocks
1741
+           'spacedlistitem':1,
1742
+           'linkable':1,
1743
+           'keeplistindent':1,
1744
+           'tableable':1,
1745
+           'barinsidequote':1,
1746
+           'tablecellstrip':1,
1747
+           'autotocwithbars':1,
1748
+           'autonumberlist':1,
1749
+           'imgalignable':1,
1750
+           'tablecellaligntype':'cell',
1751
+
1752
+           'blanksaroundpara':1,
1753
+           'blanksaroundverb':1,
1754
+           # 'blanksaroundquote':1,
1755
+           'blanksaroundlist':1,
1756
+           'blanksaroundnumlist':1,
1757
+           'blanksarounddeflist':1,
1758
+           'blanksaroundtable':1,
1759
+           'blanksaroundbar':1,
1760
+           'blanksaroundtitle':1,
1761
+           'blanksaroundnumtitle':1,
1762
+       },
1763
+       'pmw': {
1764
+           'indentverbblock':1,
1765
+           'spacedlistitem':1,
1766
+           'linkable':1,
1767
+           'labelbeforelink':1,
1768
+           # 'keeplistindent':1,
1769
+           'tableable':1,
1770
+           'barinsidequote':1,
1771
+           'tablecellstrip':1,
1772
+           'autotocwithbars':1,
1773
+           'autonumberlist':1,
1774
+           'spacedlistitemopen':1,
1775
+           'spacednumlistitemopen':1,
1776
+           'imgalignable':1,
1777
+           'tabletitlerowinbold':1,
1778
+           'tablecellaligntype':'cell',
1779
+
1780
+           'blanksaroundpara':1,
1781
+           'blanksaroundverb':1,
1782
+           'blanksaroundquote':1,
1783
+           'blanksaroundlist':1,
1784
+           'blanksaroundnumlist':1,
1785
+           'blanksarounddeflist':1,
1786
+           'blanksaroundtable':1,
1787
+           'blanksaroundbar':1,
1788
+           'blanksaroundtitle':1,
1789
+           'blanksaroundnumtitle':1,
1790
+       },
1791
+       'wiki': {
1792
+           'linkable':1,
1793
+           'tableable':1,
1794
+           'tablecellstrip':1,
1795
+           'autotocwithbars':1,
1796
+           'spacedlistitemopen':1,
1797
+           'spacednumlistitemopen':1,
1798
+           'deflisttextstrip':1,
1799
+           'autonumberlist':1,
1800
+           'imgalignable':1,
1801
+
1802
+           'blanksaroundpara':1,
1803
+           'blanksaroundverb':1,
1804
+           # 'blanksaroundquote':1,
1805
+           'blanksaroundlist':1,
1806
+           'blanksaroundnumlist':1,
1807
+           'blanksarounddeflist':1,
1808
+           'blanksaroundtable':1,
1809
+           'blanksaroundbar':1,
1810
+           'blanksaroundtitle':1,
1811
+           'blanksaroundnumtitle':1,
1812
+       },
1813
+       'man': {
1814
+           'spacedlistitem':1,
1815
+           'tagnotindentable':1,
1816
+           'tableable':1,
1817
+           'tablecellaligntype':'column',
1818
+           'tabletitlerowinbold':1,
1819
+           'tablecellstrip':1,
1820
+           'barinsidequote':1,
1821
+           'parainsidelist':0,
1822
+
1823
+           'blanksaroundpara':1,
1824
+           'blanksaroundverb':1,
1825
+           # 'blanksaroundquote':1,
1826
+           'blanksaroundlist':1,
1827
+           'blanksaroundnumlist':1,
1828
+           'blanksarounddeflist':1,
1829
+           'blanksaroundtable':1,
1830
+           # 'blanksaroundbar':1,
1831
+           'blanksaroundtitle':1,
1832
+           'blanksaroundnumtitle':1,
1833
+       },
1834
+       'pm6': {
1835
+           'keeplistindent':1,
1836
+           'verbblockfinalescape':1,
1837
+           #TODO add support for these
1838
+           # maybe set a JOINNEXT char and do it on addLineBreaks()
1839
+           'notbreaklistopen':1,
1840
+           'barinsidequote':1,
1841
+           'autotocwithbars':1,
1842
+           'onelinepara':1,
1843
+
1844
+           'blanksaroundpara':1,
1845
+           'blanksaroundverb':1,
1846
+           # 'blanksaroundquote':1,
1847
+           'blanksaroundlist':1,
1848
+           'blanksaroundnumlist':1,
1849
+           'blanksarounddeflist':1,
1850
+           # 'blanksaroundtable':1,
1851
+           # 'blanksaroundbar':1,
1852
+           'blanksaroundtitle':1,
1853
+           'blanksaroundnumtitle':1,
1854
+       },
1855
+       'creole': {
1856
+           'linkable':1,
1857
+           'tableable':1,
1858
+           'imglinkable':1,
1859
+           'tablecellstrip':1,
1860
+           'autotocwithbars':1,
1861
+           'spacedlistitemopen':1,
1862
+           'spacednumlistitemopen':1,
1863
+           'deflisttextstrip':1,
1864
+           'verbblocknotescaped':1,
1865
+           'blanksaroundpara':1,
1866
+           'blanksaroundverb':1,
1867
+           'blanksaroundquote':1,
1868
+           'blanksaroundlist':1,
1869
+           'blanksaroundnumlist':1,
1870
+           'blanksarounddeflist':1,
1871
+           'blanksaroundtable':1,
1872
+           'blanksaroundbar':1,
1873
+           'blanksaroundtitle':1,
1874
+       },
1875
+   }
1876
+   
1877
+   # Exceptions for --css-sugar
1878
+   if config['css-sugar'] and config['target'] in ('html','xhtml'):
1879
+       rules_bank['html']['indentverbblock'] = 0
1880
+       rules_bank['html']['autotocwithbars'] = 0
1881
+   
1882
+   # Get the target specific rules
1883
+   if config['target'] == 'xhtml':
1884
+       myrules = rules_bank['html'].copy()   # inheritance
1885
+       myrules.update(rules_bank['xhtml'])   # get XHTML specific
1886
+   elif config['target'] == 'art':
1887
+       myrules = rules_bank['txt'].copy()    # inheritance
1888
+       if config['slides']:
1889
+           myrules['blanksaroundtitle'] = 0
1890
+           myrules['blanksaroundnumtitle'] = 0
1891
+   else:
1892
+       myrules = rules_bank[config['target']].copy()
1893
+   
1894
+   # Populate return dictionary
1895
+   for key in allrules: ret[key] = 0        # reset all
1896
+   ret.update(myrules)                      # get rules
1897
+   
1898
+   return ret
1899
+
1900
+
1901
+##############################################################################
1902
+
1903
+
1904
+def getRegexes():
1905
+   "Returns all the regexes used to find the t2t marks"
1906
+   
1907
+   bank = {
1908
+   'blockVerbOpen':
1909
+       re.compile(r'^```\s*$'),
1910
+   'blockVerbClose':
1911
+       re.compile(r'^```\s*$'),
1912
+   'blockRawOpen':
1913
+       re.compile(r'^"""\s*$'),
1914
+   'blockRawClose':
1915
+       re.compile(r'^"""\s*$'),
1916
+   'blockTaggedOpen':
1917
+       re.compile(r"^'''\s*$"),
1918
+   'blockTaggedClose':
1919
+       re.compile(r"^'''\s*$"),
1920
+   'blockCommentOpen':
1921
+       re.compile(r'^%%%\s*$'),
1922
+   'blockCommentClose':
1923
+       re.compile(r'^%%%\s*$'),
1924
+   'quote':
1925
+       re.compile(r'^\t+'),
1926
+   '1lineVerb':
1927
+       re.compile(r'^``` (?=.)'),
1928
+   '1lineRaw':
1929
+       re.compile(r'^""" (?=.)'),
1930
+   '1lineTagged':
1931
+       re.compile(r"^''' (?=.)"),
1932
+   # mono, raw, bold, italic, underline:
1933
+   # - marks must be glued with the contents, no boundary spaces
1934
+   # - they are greedy, so in ****bold****, turns to <b>**bold**</b>
1935
+   'fontMono':
1936
+       re.compile(  r'``([^\s](|.*?[^\s])`*)``'),
1937
+   'raw':
1938
+       re.compile(  r'""([^\s](|.*?[^\s])"*)""'),
1939
+   'tagged':
1940
+       re.compile(  r"''([^\s](|.*?[^\s])'*)''"),
1941
+   'fontBold':
1942
+       re.compile(r'\*\*([^\s](|.*?[^\s])\**)\*\*'),
1943
+   'fontItalic':
1944
+       re.compile(  r'//([^\s](|.*?[^\s])/*)//'),
1945
+   'fontUnderline':
1946
+       re.compile(  r'__([^\s](|.*?[^\s])_*)__'),
1947
+   'fontStrike':
1948
+       re.compile(  r'--([^\s](|.*?[^\s])-*)--'),
1949
+   'list':
1950
+       re.compile(r'^( *)(-) (?=[^ ])'),
1951
+   'numlist':
1952
+       re.compile(r'^( *)(\+) (?=[^ ])'),
1953
+   'deflist':
1954
+       re.compile(r'^( *)(:) (.*)$'),
1955
+   'listclose':
1956
+       re.compile(r'^( *)([-+:])\s*$'),
1957
+   'bar':
1958
+       re.compile(r'^(\s*)([_=-]{20,})\s*$'),
1959
+   'table':
1960
+       re.compile(r'^ *\|\|? '),
1961
+   'blankline':
1962
+       re.compile(r'^\s*$'),
1963
+   'comment':
1964
+       re.compile(r'^%'),
1965
+   
1966
+   # Auxiliary tag regexes
1967
+   '_imgAlign'        : re.compile(r'~A~', re.I),
1968
+   '_tableAlign'      : re.compile(r'~A~', re.I),
1969
+   '_anchor'          : re.compile(r'~A~', re.I),
1970
+   '_tableBorder'     : re.compile(r'~B~', re.I),
1971
+   '_tableColAlign'   : re.compile(r'~C~', re.I),
1972
+   '_tableCellColSpan': re.compile(r'~S~', re.I),
1973
+   '_tableCellAlign'  : re.compile(r'~A~', re.I),
1974
+   }
1975
+   
1976
+   # Special char to place data on TAGs contents  (\a == bell)
1977
+   bank['x'] = re.compile('\a')
1978
+   
1979
+   # %%macroname [ (formatting) ]
1980
+   bank['macros'] = re.compile(r'%%%%(?P<name>%s)\b(\((?P<fmt>.*?)\))?' % (
1981
+       '|'.join(MACROS.keys())), re.I)
1982
+   
1983
+   # %%TOC special macro for TOC positioning
1984
+   bank['toc'] = re.compile(r'^ *%%toc\s*$', re.I)
1985
+   
1986
+   # Almost complicated title regexes ;)
1987
+   titskel = r'^ *(?P<id>%s)(?P<txt>%s)\1(\[(?P<label>[\w-]*)\])?\s*$'
1988
+   bank[   'title'] = re.compile(titskel%('[=]{1,5}','[^=](|.*[^=])'))
1989
+   bank['numtitle'] = re.compile(titskel%('[+]{1,5}','[^+](|.*[^+])'))
1990
+   
1991
+   ### Complicated regexes begin here ;)
1992
+   #
1993
+   # Textual descriptions on --help's style: [...] is optional, | is OR
1994
+   
1995
+   
1996
+   ### First, some auxiliary variables
1997
+   #
1998
+   
1999
+   # [image.EXT]
2000
+   patt_img = r'\[([\w_,.+%$#@!?+~/-]+\.(png|jpe?g|gif|eps|bmp))\]'
2001
+   
2002
+   # Link things
2003
+   # http://www.gbiv.com/protocols/uri/rfc/rfc3986.html
2004
+   # pchar: A-Za-z._~- / %FF / !$&'()*+,;= / :@
2005
+   # Recomended order: scheme://user:pass@domain/path?query=foo#anchor
2006
+   # Also works      : scheme://user:pass@domain/path#anchor?query=foo
2007
+   # TODO form: !'():
2008
+   urlskel = {
2009
+       'proto' : r'(https?|ftp|news|telnet|gopher|wais)://',
2010
+       'guess' : r'(www[23]?|ftp)\.',         # w/out proto, try to guess
2011
+       'login' : r'A-Za-z0-9_.-',             # for ftp://login@domain.com
2012
+       'pass'  : r'[^ @]*',                   # for ftp://login:pass@dom.com
2013
+       'chars' : r'A-Za-z0-9%._/~:,=$@&+-',   # %20(space), :80(port), D&D
2014
+       'anchor': r'A-Za-z0-9%._-',            # %nn(encoded)
2015
+       'form'  : r'A-Za-z0-9/%&=+:;.,$@*_-',  # .,@*_-(as is)
2016
+       'punct' : r'.,;:!?'
2017
+   }
2018
+   
2019
+   # username [ :password ] @
2020
+   patt_url_login = r'([%s]+(:%s)?@)?'%(urlskel['login'],urlskel['pass'])
2021
+   
2022
+   # [ http:// ] [ username:password@ ] domain.com [ / ]
2023
+   #     [ #anchor | ?form=data ]
2024
+   retxt_url = r'\b(%s%s|%s)[%s]+\b/*(\?[%s]+)?(#[%s]*)?'%(
2025
+       urlskel['proto'],patt_url_login, urlskel['guess'],
2026
+       urlskel['chars'],urlskel['form'],urlskel['anchor'])
2027
+   
2028
+   # filename | [ filename ] #anchor
2029
+   retxt_url_local = r'[%s]+|[%s]*(#[%s]*)'%(
2030
+       urlskel['chars'],urlskel['chars'],urlskel['anchor'])
2031
+   
2032
+   # user@domain [ ?form=data ]
2033
+   patt_email = r'\b[%s]+@([A-Za-z0-9_-]+\.)+[A-Za-z]{2,4}\b(\?[%s]+)?'%(
2034
+       urlskel['login'],urlskel['form'])
2035
+   
2036
+   # Saving for future use
2037
+   bank['_urlskel'] = urlskel
2038
+   
2039
+   ### And now the real regexes
2040
+   #
2041
+   
2042
+   bank['email'] = re.compile(patt_email,re.I)
2043
+   
2044
+   # email | url
2045
+   bank['link'] = re.compile(r'%s|%s'%(retxt_url,patt_email), re.I)
2046
+   
2047
+   # \[ label | imagetag    url | email | filename \]
2048
+   bank['linkmark'] = re.compile(
2049
+       r'\[(?P<label>%s|[^]]+) (?P<link>%s|%s|%s)\]'%(
2050
+           patt_img, retxt_url, patt_email, retxt_url_local),
2051
+       re.L+re.I)
2052
+   
2053
+   # Image
2054
+   bank['img'] = re.compile(patt_img, re.L+re.I)
2055
+   
2056
+   # Special things
2057
+   bank['special'] = re.compile(r'^%!\s*')
2058
+   return bank
2059
+### END OF regex nightmares
2060
+
2061
+################# functions for the ASCII Art backend ########################
2062
+
2063
+def aa_line(char, length):
2064
+   return char * length
2065
+
2066
+def aa_box(txt, length):
2067
+   len_txt = len(txt)
2068
+   nspace = int((length - len_txt - 4) / 2)
2069
+   line_box = " " * nspace + AA['corner'] + AA['border'] * (len_txt + 2) + AA['corner']
2070
+   # <----- nspace " " -----> "+" <----- len_txt+2 "-" -----> "+"
2071
+   #                           +-------------------------------+
2072
+   #                           | all theeeeeeeeeeeeeeeeee text |
2073
+   # <----- nspace " " -----> "| " <--------- txt ---------> " |"
2074
+   line_txt = " " * nspace + AA['side'] + ' ' + txt + ' ' + AA['side']
2075
+   return [line_box, line_txt, line_box]
2076
+
2077
+def aa_header(header_data, length, n, end):
2078
+   header = [aa_line(AA['bar2'], length)]
2079
+   header.extend(['']*int(n))  #n must be int!
2080
+   for h in 'HEADER1', 'HEADER2', 'HEADER3':
2081
+       if header_data[h]:
2082
+           header.extend(aa_box(header_data[h], length))
2083
+           header.extend(['']*int(n))  #Again, n must be int!!
2084
+   header.extend(['']*end)
2085
+   header.append(aa_line(AA['bar2'], length))
2086
+   return header
2087
+
2088
+def aa_slide(title, length):
2089
+   res = [aa_line(AA['bar2'], length)]
2090
+   res.append('')
2091
+   res.append(title.center(length))
2092
+   res.append('')
2093
+   res.append(aa_line(AA['bar2'], length))
2094
+   return res
2095
+
2096
+def aa_table(table):
2097
+    data = [row[2:-2].split(' | ') for row in table]
2098
+    n = max([len(line) for line in data])
2099
+    data = [line + (n - len(line)) * [''] for line in data]
2100
+    tab = []
2101
+    for i in range(n):
2102
+        tab.append([line[i] for line in data])
2103
+    length = [max([len(el) for el in line]) for line in tab]
2104
+    res = "+"
2105
+    for i in range(n):
2106
+        res = res + (length[i] + 2) * "-" + '+'
2107
+    ret = []
2108
+    for line in data:
2109
+        aff = "|"
2110
+        ret.append(res)
2111
+        for j,el in enumerate(line):
2112
+            aff = aff + " " + el + (length[j] - len(el) + 1) * " " + "|"
2113
+        ret.append(aff)
2114
+    ret.append(res)
2115
+    return ret
2116
+
2117
+##############################################################################
2118
+
2119
+class error(Exception):
2120
+   pass
2121
+def echo(msg):   # for quick debug
2122
+   print('\033[32;1m%s\033[m'%msg)
2123
+def Quit(msg=''):
2124
+   if msg: print(msg)
2125
+   sys.exit(0)
2126
+def Error(msg):
2127
+   msg = _("%s: Error: ")%my_name + msg
2128
+   raise error(msg)
2129
+def getTraceback():
2130
+   try:
2131
+       from traceback import format_exception
2132
+       etype, value, tb = sys.exc_info()
2133
+       return ''.join(format_exception(etype, value, tb))
2134
+   except: pass
2135
+def getUnknownErrorMessage():
2136
+   msg = '%s\n%s (%s):\n\n%s'%(
2137
+       _('Sorry! Txt2tags aborted by an unknown error.'),
2138
+       _('Please send the following Error Traceback to the author'),
2139
+       my_email, getTraceback())
2140
+   return msg
2141
+def Message(msg,level):
2142
+   if level <= VERBOSE and not QUIET:
2143
+       prefix = '-'*5
2144
+       print("%s %s"%(prefix*level, msg))
2145
+def Debug(msg,id_=0,linenr=None):
2146
+   "Show debug messages, categorized (colored or not)"
2147
+   if QUIET or not DEBUG: return
2148
+   if int(id_) not in range(8): id_ = 0
2149
+   # 0:black 1:red 2:green 3:yellow 4:blue 5:pink 6:cyan 7:white ;1:light
2150
+   ids            = ['INI','CFG','SRC','BLK','HLD','GUI','OUT','DET']
2151
+   colors_bgdark  = ['7;1','1;1','3;1','6;1','4;1','5;1','2;1','7;1']
2152
+   colors_bglight = ['0'  ,'1'  ,'3'  ,'6'  ,'4'  ,'5'  ,'2'  ,'0'  ]
2153
+   if linenr is not None: msg = "LINE %04d: %s"%(linenr,msg)
2154
+   if COLOR_DEBUG:
2155
+       if BG_LIGHT: color = colors_bglight[id_]
2156
+       else       : color = colors_bgdark[id_]
2157
+       msg = '\033[3%sm%s\033[m'%(color,msg)
2158
+   print("++ %s: %s"%(ids[id_],msg))
2159
+
2160
+def Readfile(file_path, remove_linebreaks=0, ignore_error=0):
2161
+   data = []
2162
+   if file_path == '-':
2163
+       try:    
2164
+           data = sys.stdin.readlines()
2165
+       except:
2166
+           if not ignore_error:
2167
+               Error(_('You must feed me with data on STDIN!'))
2168
+   else:
2169
+       try:
2170
+           f = open(file_path)
2171
+           data = f.readlines()
2172
+           f.close()
2173
+       except:
2174
+           if not ignore_error:
2175
+               Error(_("Cannot read file:") + ' ' + file_path)
2176
+   if remove_linebreaks:
2177
+       data = [re.sub('[\n\r]+$', '', x) for x in data]
2178
+   Message(_("File read (%d lines): %s") % (len(data), file_path), 2)
2179
+   return data
2180
+
2181
+def Savefile(file_path, contents):
2182
+   try:
2183
+       f = open(file_path, 'w')
2184
+   except:
2185
+       Error(_("Cannot open file for writing:") + ' ' + file_path)
2186
+   if isinstance(contents, type([])):
2187
+       doit = f.writelines
2188
+   else:
2189
+       doit = f.write
2190
+   doit(contents)
2191
+   f.close()
2192
+
2193
+def showdic(dic):
2194
+   for k in dic.keys(): print("%15s : %s" % (k,dic[k]))
2195
+def dotted_spaces(txt=''):
2196
+   return txt.replace(' ', '.')
2197
+
2198
+# TIP: win env vars http://www.winnetmag.com/Article/ArticleID/23873/23873.html
2199
+def get_rc_path():
2200
+   "Return the full path for the users' RC file"
2201
+   # Try to get the path from an env var. if yes, we're done
2202
+   user_defined = os.environ.get('T2TCONFIG')
2203
+   if user_defined: return user_defined
2204
+   # Env var not found, so perform automatic path composing
2205
+   # Set default filename according system platform
2206
+   rc_names = {'default':'.txt2tagsrc', 'win':'_t2trc'}
2207
+   rc_file = rc_names.get(sys.platform[:3]) or rc_names['default']
2208
+   # The file must be on the user directory, but where is this dir?
2209
+   rc_dir_search = ['HOME', 'HOMEPATH']
2210
+   for var in rc_dir_search:
2211
+       rc_dir = os.environ.get(var)
2212
+       if rc_dir: break
2213
+   # rc dir found, now we must join dir+file to compose the full path
2214
+   if rc_dir:
2215
+       # Compose path and return it if the file exists
2216
+       rc_path = os.path.join(rc_dir, rc_file)
2217
+       # On windows, prefix with the drive (%homedrive%: 2k/XP/NT)
2218
+       if sys.platform.startswith('win'):
2219
+           rc_drive = os.environ.get('HOMEDRIVE')
2220
+           rc_path = os.path.join(rc_drive,rc_path)
2221
+       return rc_path
2222
+   # Sorry, not found
2223
+   return ''
2224
+
2225
+
2226
+
2227
+##############################################################################
2228
+
2229
+class CommandLine:
2230
+   """
2231
+   Command Line class - Masters command line
2232
+
2233
+   This class checks and extract data from the provided command line.
2234
+   The --long options and flags are taken from the global OPTIONS,
2235
+   FLAGS and ACTIONS dictionaries. The short options are registered
2236
+   here, and also their equivalence to the long ones.
2237
+
2238
+   _compose_short_opts() -> str
2239
+   _compose_long_opts() -> list
2240
+       Compose the valid short and long options list, on the
2241
+       'getopt' format.
2242
+
2243
+   parse() -> (opts, args)
2244
+       Call getopt to check and parse the command line.
2245
+       It expects to receive the command line as a list, and
2246
+       without the program name (sys.argv[1:]).
2247
+
2248
+   get_raw_config() -> [RAW config]
2249
+       Scans command line and convert the data to the RAW config
2250
+       format. See ConfigMaster class to the RAW format description.
2251
+       Optional 'ignore' and 'filter_' arguments are used to filter
2252
+       in or out specified keys.
2253
+
2254
+   compose_cmdline(dict) -> [Command line]
2255
+       Compose a command line list from an already parsed config
2256
+       dictionary, generated from RAW by ConfigMaster(). Use
2257
+       this to compose an optimal command line for a group of
2258
+       options.
2259
+   
2260
+   The get_raw_config() calls parse(), so the typical use of this
2261
+   class is:
2262
+   
2263
+            raw = CommandLine().get_raw_config(sys.argv[1:])
2264
+   """
2265
+   def __init__(self):
2266
+       self.all_options = list(OPTIONS.keys())
2267
+       self.all_flags   = list(FLAGS.keys())
2268
+       self.all_actions = list(ACTIONS.keys())
2269
+       
2270
+       # short:long options equivalence
2271
+       self.short_long = {
2272
+           'C':'config-file',
2273
+           'h':'help',
2274
+           'H':'no-headers',
2275
+           'i':'infile',
2276
+           'n':'enum-title',
2277
+           'o':'outfile',
2278
+           'q':'quiet',
2279
+           't':'target',
2280
+           'v':'verbose',
2281
+           'V':'version',
2282
+       }
2283
+       
2284
+       # Compose valid short and long options data for getopt
2285
+       self.short_opts = self._compose_short_opts()
2286
+       self.long_opts  = self._compose_long_opts()
2287
+   
2288
+   def _compose_short_opts(self):
2289
+       "Returns a string like 'hVt:o' with all short options/flags"
2290
+       ret = []
2291
+       for opt in self.short_long.keys():
2292
+           long_ = self.short_long[opt]
2293
+           if long_ in self.all_options: # is flag or option?
2294
+               opt = opt+':'        # option: have param
2295
+           ret.append(opt)
2296
+       #Debug('Valid SHORT options: %s'%ret)
2297
+       return ''.join(ret)
2298
+   
2299
+   def _compose_long_opts(self):
2300
+       "Returns a list with all the valid long options/flags"
2301
+       ret = [x+'=' for x in self.all_options]          # add =
2302
+       ret.extend(self.all_flags)                           # flag ON
2303
+       ret.extend(self.all_actions)                         # actions
2304
+       ret.extend(['no-'+x for x in self.all_flags])    # add no-*
2305
+       ret.extend(['no-style','no-encoding'])               # turn OFF
2306
+       ret.extend(['no-outfile','no-infile'])               # turn OFF
2307
+       ret.extend(['no-dump-config', 'no-dump-source'])     # turn OFF
2308
+       ret.extend(['no-targets'])                           # turn OFF
2309
+       #Debug('Valid LONG options: %s'%ret)
2310
+       return ret
2311
+   
2312
+   def _tokenize(self, cmd_string=''):
2313
+       "Convert a command line string to a list"
2314
+       #TODO protect quotes contents -- Don't use it, pass cmdline as list
2315
+       return cmd_string.split()
2316
+   
2317
+   def parse(self, cmdline=[]):
2318
+       "Check/Parse a command line list     TIP: no program name!"
2319
+       # Get the valid options
2320
+       short, long_ = self.short_opts, self.long_opts
2321
+       # Parse it!
2322
+       try:
2323
+           opts, args = getopt.getopt(cmdline, short, long_)
2324
+       except getopt.error as errmsg:
2325
+           Error(_("%s (try --help)")%errmsg)
2326
+       return (opts, args)
2327
+   
2328
+   def get_raw_config(self, cmdline=[], ignore=[], filter_=[], relative=0):
2329
+       "Returns the options/arguments found as RAW config"
2330
+       
2331
+       if not cmdline: return []
2332
+       ret = []
2333
+       
2334
+       # We need lists, not strings (such as from %!options)
2335
+       if type(cmdline) in (type(''), type('')):
2336
+           cmdline = self._tokenize(cmdline)
2337
+
2338
+       # Extract name/value pair of all configs, check for invalid names
2339
+       options, arguments = self.parse(cmdline[:])
2340
+
2341
+       # Some cleanup on the raw config
2342
+       for name, value in options:
2343
+           
2344
+           # Remove leading - and --
2345
+           name = re.sub('^--?', '', name)
2346
+
2347
+           # Fix old misspelled --suGGar, --no-suGGar
2348
+           name = name.replace('suggar', 'sugar')
2349
+
2350
+           # Translate short option to long
2351
+           if len(name) == 1:
2352
+               name = self.short_long[name]
2353
+
2354
+           # Outfile exception: path relative to PWD
2355
+           if name == 'outfile' and relative and value not in [STDOUT, MODULEOUT]:
2356
+               value = os.path.abspath(value)
2357
+
2358
+           # -C, --config-file inclusion, path relative to PWD
2359
+           if name == 'config-file':
2360
+               ret.extend(ConfigLines().include_config_file(value))
2361
+               continue
2362
+           
2363
+           # Save this config
2364
+           ret.append(['all', name, value])
2365
+       
2366
+       # All configuration was read and saved
2367
+       
2368
+       # Get infile, if any
2369
+       while arguments:
2370
+           infile = arguments.pop(0)
2371
+           ret.append(['all', 'infile', infile])
2372
+       
2373
+       # Apply 'ignore' and 'filter_' rules (filter_ is stronger)
2374
+       if (ignore or filter_):
2375
+           filtered = []
2376
+           for target, name, value in ret:
2377
+               if (filter_ and name in filter_) or \
2378
+                  (ignore and name not in ignore):
2379
+                   filtered.append([target, name, value])
2380
+           ret = filtered[:]
2381
+       
2382
+       # Add the original command line string as 'realcmdline'
2383
+       ret.append( ['all', 'realcmdline', cmdline] )
2384
+       
2385
+       return ret
2386
+   
2387
+   def compose_cmdline(self, conf={}, no_check=0):
2388
+       "compose a full (and diet) command line from CONF dict"
2389
+       if not conf: return []
2390
+       args = []
2391
+       dft_options = OPTIONS.copy()
2392
+       cfg = conf.copy()
2393
+       valid_opts = self.all_options + self.all_flags
2394
+       use_short = {'no-headers':'H', 'enum-title':'n'}
2395
+       # Remove useless options
2396
+       if not no_check and cfg.get('toc-only'):
2397
+           if 'no-headers' in cfg:
2398
+               del cfg['no-headers']
2399
+           if 'outfile' in cfg:
2400
+               del cfg['outfile']      # defaults to STDOUT
2401
+           if cfg.get('target') == 'txt':
2402
+               del cfg['target']       # already default
2403
+           args.append('--toc-only')  # must be the first
2404
+           del cfg['toc-only']
2405
+       # Add target type
2406
+       if 'target' in cfg:
2407
+           args.append('-t '+cfg['target'])
2408
+           del cfg['target']
2409
+       # Add other options
2410
+       for key in cfg.keys():
2411
+           if key not in valid_opts: continue  # may be a %!setting
2412
+           if key == 'outfile' or key == 'infile': continue # later
2413
+           val = cfg[key]
2414
+           if not val: continue
2415
+           # Default values are useless on cmdline
2416
+           if val == dft_options.get(key): continue
2417
+           # -short format
2418
+           if key in use_short.keys():
2419
+               args.append('-'+use_short[key])
2420
+               continue
2421
+           # --long format
2422
+           if key in self.all_flags: # add --option
2423
+               args.append('--'+key)
2424
+           else:                     # add --option=value
2425
+               args.append('--%s=%s'%(key,val))
2426
+       # The outfile using -o
2427
+       if 'outfile' in cfg and \
2428
+          cfg['outfile'] != dft_options.get('outfile'):
2429
+           args.append('-o '+cfg['outfile'])
2430
+       # Place input file(s) always at the end
2431
+       if 'infile' in cfg:
2432
+           args.append(' '.join(cfg['infile']))
2433
+       # Return as a nice list
2434
+       Debug("Diet command line: %s"%' '.join(args), 1)
2435
+       return args
2436
+
2437
+##############################################################################
2438
+
2439
+class SourceDocument:
2440
+   """
2441
+   SourceDocument class - scan document structure, extract data
2442
+   
2443
+   It knows about full files. It reads a file and identify all
2444
+   the areas beginning (Head,Conf,Body). With this info it can
2445
+   extract each area contents.
2446
+   Note: the original line break is removed.
2447
+   
2448
+   DATA:
2449
+     self.arearef - Save Head, Conf, Body init line number
2450
+     self.areas   - Store the area names which are not empty
2451
+     self.buffer  - The full file contents (with NO \\r, \\n)
2452
+
2453
+   METHODS:
2454
+     get()   - Access the contents of an Area. Example:
2455
+               config = SourceDocument(file).get('conf')
2456
+   
2457
+     split() - Get all the document Areas at once. Example:
2458
+               head, conf, body = SourceDocument(file).split()
2459
+   
2460
+   RULES:
2461
+       * The document parts are sequential: Head, Conf and Body.
2462
+       * One ends when the next begins.
2463
+       * The Conf Area is optional, so a document can have just
2464
+         Head and Body Areas.
2465
+   
2466
+       These are the Areas limits:
2467
+         - Head Area: the first three lines
2468
+         - Body Area: from the first valid text line to the end
2469
+         - Conf Area: the comments between Head and Body Areas
2470
+
2471
+       Exception: If the first line is blank, this means no
2472
+       header info, so the Head Area is just the first line.
2473
+   """
2474
+   def __init__(self, filename='', contents=[]):
2475
+       self.areas = ['head','conf','body']
2476
+       self.arearef = []
2477
+       self.areas_fancy = ''
2478
+       self.filename = filename
2479
+       self.buffer = []
2480
+       if filename:
2481
+           self.scan_file(filename)
2482
+       elif contents:
2483
+           self.scan(contents)
2484
+   
2485
+   def split(self):
2486
+       "Returns all document parts, splitted into lists."
2487
+       return self.get('head'), self.get('conf'), self.get('body')
2488
+   
2489
+   def get(self, areaname):
2490
+       "Returns head|conf|body contents from self.buffer"
2491
+       # Sanity
2492
+       if areaname not in self.areas: return []
2493
+       if not self.buffer           : return []
2494
+       # Go get it
2495
+       bufini = 1
2496
+       bufend = len(self.buffer)
2497
+       if   areaname == 'head':
2498
+           ini = bufini
2499
+           end = self.arearef[1] or self.arearef[2] or bufend
2500
+       elif areaname == 'conf':
2501
+           ini = self.arearef[1]
2502
+           end = self.arearef[2] or bufend
2503
+       elif areaname == 'body':
2504
+           ini = self.arearef[2]
2505
+           end = bufend
2506
+       else:
2507
+           Error("Unknown Area name '%s'"%areaname)
2508
+       lines = self.buffer[ini:end]
2509
+       # Make sure head will always have 3 lines
2510
+       while areaname == 'head' and len(lines) < 3:
2511
+           lines.append('')
2512
+       return lines
2513
+   
2514
+   def scan_file(self, filename):
2515
+       Debug("source file: %s"%filename)
2516
+       Message(_("Loading source document"),1)
2517
+       buf = Readfile(filename, remove_linebreaks=1)
2518
+       self.scan(buf)
2519
+   
2520
+   def scan(self, lines):
2521
+       "Run through source file and identify head/conf/body areas"
2522
+       buf = lines
2523
+       if len(buf) == 0:
2524
+           Error(_('The input file is empty: %s')%self.filename)
2525
+       cfg_parser = ConfigLines().parse_line
2526
+       buf.insert(0, '')                         # text start at pos 1
2527
+       ref = [1,4,0]
2528
+       if not buf[1].strip():                    # no header
2529
+           ref[0] = 0 ; ref[1] = 2
2530
+       rgx = getRegexes()
2531
+       on_comment_block = 0
2532
+       for i in range(ref[1],len(buf)):         # find body init:
2533
+           # Handle comment blocks inside config area
2534
+           if not on_comment_block \
2535
+              and rgx['blockCommentOpen'].search(buf[i]):
2536
+               on_comment_block = 1
2537
+               continue
2538
+           if on_comment_block \
2539
+              and rgx['blockCommentOpen'].search(buf[i]):
2540
+               on_comment_block = 0
2541
+               continue
2542
+           if on_comment_block: continue
2543
+           
2544
+           if buf[i].strip() and (           # ... not blank and
2545
+              buf[i][0] != '%' or            # ... not comment or
2546
+              rgx['macros'].match(buf[i]) or # ... %%macro
2547
+              rgx['toc'].match(buf[i])    or # ... %%toc
2548
+              cfg_parser(buf[i],'include')[1] or # ... %!include
2549
+              cfg_parser(buf[i],'csv')[1]        # ... %!csv
2550
+           ):
2551
+               ref[2] = i ; break
2552
+       if ref[1] == ref[2]: ref[1] = 0           # no conf area
2553
+       for i in 0,1,2:                           # del !existent
2554
+           if ref[i] >= len(buf): ref[i] = 0 # title-only
2555
+           if not ref[i]: self.areas[i] = ''
2556
+       Debug('Head,Conf,Body start line: %s'%ref)
2557
+       self.arearef = ref                        # save results
2558
+       self.buffer  = buf
2559
+       # Fancyness sample: head conf body (1 4 8)
2560
+       self.areas_fancy = "%s (%s)"%(
2561
+           ' '.join(self.areas),
2562
+           ' '.join(map(str, [x or '' for x in ref])))
2563
+       Message(_("Areas found: %s")%self.areas_fancy, 2)
2564
+   
2565
+   def get_raw_config(self):
2566
+       "Handy method to get the CONF area RAW config (if any)"
2567
+       if not self.areas.count('conf'): return []
2568
+       Message(_("Scanning source document CONF area"),1)
2569
+       raw = ConfigLines(
2570
+           file_=self.filename, lines=self.get('conf'),
2571
+           first_line=self.arearef[1]).get_raw_config()
2572
+       Debug("document raw config: %s"%raw, 1)
2573
+       return raw
2574
+
2575
+##############################################################################
2576
+
2577
+class ConfigMaster:
2578
+   """
2579
+   ConfigMaster class - the configuration wizard
2580
+   
2581
+   This class is the configuration master. It knows how to handle
2582
+   the RAW and PARSED config format. It also performs the sanity
2583
+   checking for a given configuration.
2584
+   
2585
+   DATA:
2586
+     self.raw         - Stores the config on the RAW format
2587
+     self.parsed      - Stores the config on the PARSED format
2588
+     self.defaults    - Stores the default values for all keys
2589
+     self.off         - Stores the OFF values for all keys
2590
+     self.multi       - List of keys which can have multiple values
2591
+     self.numeric     - List of keys which value must be a number
2592
+     self.incremental - List of keys which are incremental
2593
+   
2594
+        RAW FORMAT:
2595
+     The RAW format is a list of lists, being each mother list item
2596
+     a full configuration entry. Any entry is a 3 item list, on
2597
+     the following format: [ TARGET, KEY, VALUE ]
2598
+     Being a list, the order is preserved, so it's easy to use
2599
+     different kinds of configs, as CONF area and command line,
2600
+     respecting the precedence.
2601
+     The special target 'all' is used when no specific target was
2602
+     defined on the original config.
2603
+   
2604
+   PARSED FORMAT:
2605
+     The PARSED format is a dictionary, with all the 'key : value'
2606
+     found by reading the RAW config. The self.target contents
2607
+     matters, so this dictionary only contains the target's
2608
+     config. The configs of other targets are ignored.
2609
+   
2610
+   The CommandLine and ConfigLines classes have the get_raw_config()
2611
+   method which convert the configuration found to the RAW format.
2612
+   Just feed it to parse() and get a brand-new ready-to-use config
2613
+   dictionary. Example:
2614
+   
2615
+       >>> raw = CommandLine().get_raw_config(['-n', '-H'])
2616
+       >>> print raw
2617
+       [['all', 'enum-title', ''], ['all', 'no-headers', '']]
2618
+       >>> parsed = ConfigMaster(raw).parse()
2619
+       >>> print parsed
2620
+       {'enum-title': 1, 'headers': 0}
2621
+   """
2622
+   def __init__(self, raw=[], target=''):
2623
+       self.raw          = raw
2624
+       self.target       = target
2625
+       self.parsed       = {}
2626
+       self.dft_options  = OPTIONS.copy()
2627
+       self.dft_flags    = FLAGS.copy()
2628
+       self.dft_actions  = ACTIONS.copy()
2629
+       self.dft_settings = SETTINGS.copy()
2630
+       self.defaults     = self._get_defaults()
2631
+       self.off          = self._get_off()
2632
+       self.incremental  = ['verbose']
2633
+       self.numeric      = ['toc-level', 'split', 'width', 'height']
2634
+       self.multi        = ['infile', 'preproc', 'postproc', 'options', 'style']
2635
+   
2636
+   def _get_defaults(self):
2637
+       "Get the default values for all config/options/flags"
2638
+       empty = {}
2639
+       for kw in CONFIG_KEYWORDS: empty[kw] = ''
2640
+       empty.update(self.dft_options)
2641
+       empty.update(self.dft_flags)
2642
+       empty.update(self.dft_actions)
2643
+       empty.update(self.dft_settings)
2644
+       empty['realcmdline'] = ''  # internal use only
2645
+       empty['sourcefile']  = ''  # internal use only
2646
+       return empty
2647
+   
2648
+   def _get_off(self):
2649
+       "Turns OFF all the config/options/flags"
2650
+       off = {}
2651
+       for key in self.defaults.keys():
2652
+           kind = type(self.defaults[key])
2653
+           if isinstance(0, kind):
2654
+               off[key] = 0
2655
+           elif isinstance('', kind):
2656
+               off[key] = ''
2657
+           elif isinstance([], kind):
2658
+               off[key] = []
2659
+           else:
2660
+               Error('ConfigMaster: %s: Unknown type' % key)
2661
+       return off
2662
+   
2663
+   def _check_target(self):
2664
+       "Checks if the target is already defined. If not, do it"
2665
+       if not self.target:
2666
+           self.target = self.find_value('target')
2667
+   
2668
+   def get_target_raw(self):
2669
+       "Returns the raw config for self.target or 'all'"
2670
+       ret = []
2671
+       self._check_target()
2672
+       for entry in self.raw:
2673
+           if entry[0] == self.target or entry[0] == 'all':
2674
+               ret.append(entry)
2675
+       return ret
2676
+   
2677
+   def add(self, key, val):
2678
+       "Adds the key:value pair to the config dictionary (if needed)"
2679
+       # %!options
2680
+       if key == 'options':
2681
+           ignoreme = list(self.dft_actions.keys()) + ['target']
2682
+           ignoreme.remove('dump-config')
2683
+           ignoreme.remove('dump-source')
2684
+           ignoreme.remove('targets')
2685
+           raw_opts = CommandLine().get_raw_config(
2686
+               val, ignore=ignoreme)
2687
+           for target, key, val in raw_opts:
2688
+               self.add(key, val)
2689
+           return
2690
+       # The no- prefix turns OFF this key
2691
+       if key.startswith('no-'):
2692
+           key = key[3:]              # remove prefix
2693
+           val = self.off.get(key)    # turn key OFF
2694
+       # Is this key valid?
2695
+       if key not in self.defaults.keys():
2696
+           Debug('Bogus Config %s:%s'%(key,val),1)
2697
+           return
2698
+       # Is this value the default one?
2699
+       if val == self.defaults.get(key):
2700
+           # If default value, remove previous key:val
2701
+           if key in self.parsed:
2702
+               del self.parsed[key]
2703
+           # Nothing more to do
2704
+           return
2705
+       # Flags ON comes empty. we'll add the 1 value now
2706
+       if val == '' and (
2707
+          key in self.dft_flags.keys() or
2708
+          key in self.dft_actions.keys()):
2709
+           val = 1
2710
+       # Multi value or single?
2711
+       if key in self.multi:
2712
+           # First one? start new list
2713
+           if key not in self.parsed:
2714
+               self.parsed[key] = []
2715
+           self.parsed[key].append(val)
2716
+       # Incremental value? so let's add it
2717
+       elif key in self.incremental:
2718
+           self.parsed[key] = (self.parsed.get(key) or 0) + val
2719
+       else:
2720
+           self.parsed[key] = val
2721
+       fancykey = dotted_spaces("%12s"%key)
2722
+       Message(_("Added config %s : %s")%(fancykey,val),3)
2723
+   
2724
+   def get_outfile_name(self, config={}):
2725
+       "Dirname is the same for {in,out}file"
2726
+       infile, outfile = config['sourcefile'], config['outfile']
2727
+       if outfile and outfile not in (STDOUT, MODULEOUT) \
2728
+          and not os.path.isabs(outfile):
2729
+           outfile = os.path.join(os.path.dirname(infile), outfile)
2730
+       if infile == STDIN    and not outfile: outfile = STDOUT
2731
+       if infile == MODULEIN and not outfile: outfile = MODULEOUT
2732
+       if not outfile and (infile and config.get('target')):
2733
+           basename = re.sub('\.(txt|t2t)$','',infile)
2734
+           outfile = "%s.%s"%(basename, config['target'])
2735
+       Debug(" infile: '%s'"%infile , 1)
2736
+       Debug("outfile: '%s'"%outfile, 1)
2737
+       return outfile
2738
+   
2739
+   def sanity(self, config, gui=0):
2740
+       "Basic config sanity checking"
2741
+       global AA
2742
+       if not config: return {}
2743
+       target = config.get('target')
2744
+       # Some actions don't require target specification
2745
+       if not target:
2746
+           for action in NO_TARGET:
2747
+               if config.get(action):
2748
+                   target = 'txt'
2749
+                   break
2750
+       # On GUI, some checking are skipped
2751
+       if not gui:
2752
+           # We *need* a target
2753
+           if not target:
2754
+               Error(_('No target specified (try --help)') + '\n\n' +
2755
+               _('Please inform a target using the -t option or the %!target command.') + '\n' +
2756
+               _('Example:') + ' %s -t html %s' % (my_name, _('file.t2t')) + '\n\n' +
2757
+               _("Run 'txt2tags --targets' to see all the available targets."))
2758
+           # And of course, an infile also
2759
+           # TODO#1: It seems that this checking is never reached
2760
+           if not config.get('infile'):
2761
+               Error(_('Missing input file (try --help)'))
2762
+           # Is the target valid?
2763
+           if not TARGETS.count(target):
2764
+               Error(_("Invalid target '%s'") % target + '\n\n' +
2765
+               _("Run 'txt2tags --targets' to see all the available targets."))
2766
+       # Ensure all keys are present
2767
+       empty = self.defaults.copy() ; empty.update(config)
2768
+       config = empty.copy()
2769
+       # Check integers options
2770
+       for key in config.keys():
2771
+           if key in self.numeric:
2772
+               try:
2773
+                   config[key] = int(config[key])
2774
+               except ValueError:
2775
+                   Error(_('--%s value must be a number') % key)
2776
+       # Check split level value
2777
+       if config['split'] not in (0,1,2):
2778
+           Error(_('Option --split must be 0, 1 or 2'))
2779
+       # Slides needs width and height
2780
+       if config['slides'] and target == 'art':
2781
+           if not config['width']:
2782
+               config['width'] = DFT_SLIDE_WIDTH
2783
+           if not config['height']:
2784
+               config['height'] = DFT_SLIDE_HEIGHT
2785
+       # ASCII Art needs a width
2786
+       if target == 'art' and not config['width']:
2787
+           config['width'] = DFT_TEXT_WIDTH
2788
+       # Check/set user ASCII Art formatting characters
2789
+       if config['art-chars']:
2790
+           if len(config['art-chars']) != len(AA_VALUES):
2791
+               Error(_("--art-chars: Expected %i chars, got %i") % (
2792
+                   len(AA_VALUES), len(config['art-chars'])))
2793
+           else:
2794
+               AA = dict(zip(AA_KEYS, config['art-chars']))
2795
+       # --toc-only is stronger than others
2796
+       if config['toc-only']:
2797
+           config['headers'] = 0
2798
+           config['toc']     = 0
2799
+           config['split']   = 0
2800
+           config['gui']     = 0
2801
+           config['outfile'] = config['outfile'] or STDOUT
2802
+       # Splitting is disable for now (future: HTML only, no STDOUT)
2803
+       config['split'] = 0
2804
+       # Restore target
2805
+       config['target'] = target
2806
+       # Set output file name
2807
+       config['outfile'] = self.get_outfile_name(config)
2808
+       # Checking suicide
2809
+       if config['sourcefile'] == config['outfile'] and \
2810
+          config['outfile'] not in [STDOUT,MODULEOUT] and not gui:
2811
+           Error(_("Input and Output files are the same: %s") % config['outfile'])
2812
+       return config
2813
+   
2814
+   def parse(self):
2815
+       "Returns the parsed config for the current target"
2816
+       raw = self.get_target_raw()
2817
+       for target, key, value in raw:
2818
+           self.add(key, value)
2819
+       Message(_("Added the following keys: %s") % ', '.join(self.parsed.keys()), 2)
2820
+       return self.parsed.copy()
2821
+   
2822
+   def find_value(self, key='', target=''):
2823
+       "Scans ALL raw config to find the desired key"
2824
+       ret = []
2825
+       # Scan and save all values found
2826
+       for targ, k, val in self.raw:
2827
+           if k == key and (targ == target or targ == 'all'):
2828
+               ret.append(val)
2829
+       if not ret: return ''
2830
+       # If not multi value, return only the last found
2831
+       if key in self.multi: return ret
2832
+       else                : return ret[-1]
2833
+
2834
+########################################################################
2835
+
2836
+class ConfigLines:
2837
+   """
2838
+   ConfigLines class - the config file data extractor
2839
+   
2840
+   This class reads and parse the config lines on the %!key:val
2841
+   format, converting it to RAW config. It deals with user
2842
+   config file (RC file), source document CONF area and
2843
+   %!includeconf directives.
2844
+
2845
+   Call it passing a file name or feed the desired config lines.
2846
+   Then just call the get_raw_config() method and wait to
2847
+   receive the full config data on the RAW format. This method
2848
+   also follows the possible %!includeconf directives found on
2849
+   the config lines. Example:
2850
+
2851
+       raw = ConfigLines(file=".txt2tagsrc").get_raw_config()
2852
+
2853
+   The parse_line() method is also useful to be used alone,
2854
+   to identify and tokenize a single config line. For example,
2855
+   to get the %!include command components, on the source
2856
+   document BODY:
2857
+   
2858
+       target, key, value = ConfigLines().parse_line(body_line)
2859
+   """
2860
+   def __init__(self, file_='', lines=[], first_line=1):
2861
+       self.file = file_ or 'NOFILE'
2862
+       self.lines = lines
2863
+       self.first_line = first_line
2864
+   
2865
+   def load_lines(self):
2866
+       "Make sure we've loaded the file contents into buffer"
2867
+       if not self.lines and not self.file:
2868
+           Error("ConfigLines: No file or lines provided")
2869
+       if not self.lines:
2870
+           self.lines = self.read_config_file(self.file)
2871
+   
2872
+   def read_config_file(self, filename=''):
2873
+       "Read a Config File contents, aborting on invalid line"
2874
+       if not filename: return []
2875
+       errormsg = _("Invalid CONFIG line on %s")+"\n%03d:%s"
2876
+       lines = Readfile(filename, remove_linebreaks=1)
2877
+       # Sanity: try to find invalid config lines
2878
+       for i in range(len(lines)):
2879
+           line = lines[i].rstrip()
2880
+           if not line: continue  # empty
2881
+           if line[0] != '%': Error(errormsg%(filename,i+1,line))
2882
+       return lines
2883
+   
2884
+   def include_config_file(self, file_=''):
2885
+       "Perform the %!includeconf action, returning RAW config"
2886
+       if not file_: return []
2887
+       # Current dir relative to the current file (self.file)
2888
+       current_dir = os.path.dirname(self.file)
2889
+       file_ = os.path.join(current_dir, file_)
2890
+       # Read and parse included config file contents
2891
+       lines = self.read_config_file(file_)
2892
+       return ConfigLines(file_=file_, lines=lines).get_raw_config()
2893
+   
2894
+   def get_raw_config(self):
2895
+       "Scan buffer and extract all config as RAW (including includes)"
2896
+       ret = []
2897
+       self.load_lines()
2898
+       first = self.first_line
2899
+       for i in range(len(self.lines)):
2900
+           line = self.lines[i]
2901
+           Message(_("Processing line %03d: %s")%(first+i,line),2)
2902
+           target, key, val = self.parse_line(line)
2903
+           if not key: continue    # no config on this line
2904
+           if key == 'includeconf':
2905
+               err = _('A file cannot include itself (loop!)')
2906
+               if val == self.file:
2907
+                   Error("%s: %%!includeconf: %s" % (err, self.file))
2908
+               more_raw = self.include_config_file(val)
2909
+               ret.extend(more_raw)
2910
+               Message(_("Finished Config file inclusion: %s") % val, 2)
2911
+           else:
2912
+               ret.append([target, key, val])
2913
+               Message(_("Added %s")%key,3)
2914
+       return ret
2915
+   
2916
+   def parse_line(self, line='', keyname='', target=''):
2917
+       "Detects %!key:val config lines and extract data from it"
2918
+       empty = ['', '', '']
2919
+       if not line: return empty
2920
+       no_target = ['target', 'includeconf']
2921
+       re_name   = keyname or '[a-z]+'
2922
+       re_target = target  or '[a-z]*'
2923
+       # XXX TODO <value>\S.+?  requires TWO chars, breaks %!include:a
2924
+       cfgregex  = re.compile("""
2925
+           ^%%!\s*               # leading id with opt spaces
2926
+           (?P<name>%s)\s*       # config name
2927
+           (\((?P<target>%s)\))? # optional target spec inside ()
2928
+           \s*:\s*               # key:value delimiter with opt spaces
2929
+           (?P<value>\S.+?)      # config value
2930
+           \s*$                  # rstrip() spaces and hit EOL
2931
+           """%(re_name, re_target), re.I+re.VERBOSE)
2932
+       prepostregex = re.compile("""
2933
+                                     # ---[ PATTERN ]---
2934
+           ^( "([^"]*)"          # "double quoted" or
2935
+           | '([^']*)'           # 'single quoted' or
2936
+           | ([^\s]+)            # single_word
2937
+           )
2938
+           \s+                   # separated by spaces
2939
+       
2940
+                                     # ---[ REPLACE ]---
2941
+           ( "([^"]*)"           # "double quoted" or
2942
+           | '([^']*)'           # 'single quoted' or
2943
+           | (.*)                # anything
2944
+           )
2945
+           \s*$
2946
+           """, re.VERBOSE)
2947
+       guicolors = re.compile("^([^\s]+\s+){3}[^\s]+") # 4 tokens
2948
+       
2949
+       # Give me a match or get out
2950
+       match = cfgregex.match(line)
2951
+       if not match: return empty
2952
+       
2953
+       # Save information about this config
2954
+       name   = (match.group('name') or '').lower()
2955
+       target = (match.group('target') or 'all').lower()
2956
+       value  = match.group('value')
2957
+       
2958
+       # %!keyword(target) not allowed for these
2959
+       if name in no_target and match.group('target'):
2960
+           Error(
2961
+               _("You can't use (target) with %s") % ('%!' + name)
2962
+               + "\n%s" % line)
2963
+       
2964
+       # Force no_target keywords to be valid for all targets
2965
+       if name in no_target:
2966
+           target = 'all'
2967
+       
2968
+       # Special config for GUI colors
2969
+       if name == 'guicolors':
2970
+           valmatch = guicolors.search(value)
2971
+           if not valmatch: return empty
2972
+           value = re.split('\s+', value)
2973
+       
2974
+       # Special config with two quoted values (%!preproc: "foo" 'bar')
2975
+       if name == 'preproc' or name == 'postproc':
2976
+           valmatch = prepostregex.search(value)
2977
+           if not valmatch: return empty
2978
+           getval = valmatch.group
2979
+           patt   = getval(2) or getval(3) or getval(4) or ''
2980
+           repl   = getval(6) or getval(7) or getval(8) or ''
2981
+           value  = (patt, repl)
2982
+       return [target, name, value]
2983
+
2984
+##############################################################################
2985
+
2986
+class MaskMaster:
2987
+   "(Un)Protect important structures from escaping and formatting"
2988
+   def __init__(self):
2989
+       self.linkmask  = 'vvvLINKvvv'
2990
+       self.monomask  = 'vvvMONOvvv'
2991
+       self.macromask = 'vvvMACROvvv'
2992
+       self.rawmask   = 'vvvRAWvvv'
2993
+       self.taggedmask= 'vvvTAGGEDvvv'
2994
+       self.tocmask   = 'vvvTOCvvv'
2995
+       self.macroman  = MacroMaster()
2996
+       self.reset()
2997
+   
2998
+   def reset(self):
2999
+       self.linkbank = []
3000
+       self.monobank = []
3001
+       self.macrobank = []
3002
+       self.rawbank = []
3003
+       self.taggedbank = []
3004
+   
3005
+   def mask(self, line=''):
3006
+       global AUTOTOC
3007
+
3008
+       # The verbatim, raw and tagged inline marks are mutually exclusive.
3009
+       # This means that one can't appear inside the other.
3010
+       # If found, the inner marks must be ignored.
3011
+       # Example: ``foo ""bar"" ''baz''``
3012
+       # In HTML: <code>foo ""bar"" ''baz''</code>
3013
+       #
3014
+       # The trick here is to protect the mark who appears first on the line.
3015
+       # The three regexes are tried and the one with the lowest index wins.
3016
+       # If none is found (else), we get out of the loop.
3017
+       #
3018
+       while True:
3019
+           
3020
+           # Try to match the line for the three marks
3021
+           # Note: 'z' > 999999
3022
+           #
3023
+           t = r = v = 1000000  #Python 3 doesn't allow comparison between str and int!
3024
+           try: t = regex['tagged'].search(line).start()
3025
+           except: pass
3026
+           try: r = regex['raw'].search(line).start()
3027
+           except: pass
3028
+           try: v = regex['fontMono'].search(line).start()
3029
+           except: pass
3030
+
3031
+           # Protect tagged text
3032
+           if t >= 0 and t < r and t < v:
3033
+               txt = regex['tagged'].search(line).group(1)
3034
+               self.taggedbank.append(txt)
3035
+               line = regex['tagged'].sub(self.taggedmask,line,1)
3036
+
3037
+           # Protect raw text
3038
+           elif r >= 0 and r < t and r < v:
3039
+               txt = regex['raw'].search(line).group(1)
3040
+               txt = doEscape(TARGET,txt)
3041
+               self.rawbank.append(txt)
3042
+               line = regex['raw'].sub(self.rawmask,line,1)
3043
+
3044
+           # Protect verbatim text
3045
+           elif v >= 0 and v < t and v < r:
3046
+               txt = regex['fontMono'].search(line).group(1)
3047
+               txt = doEscape(TARGET,txt)
3048
+               self.monobank.append(txt)
3049
+               line = regex['fontMono'].sub(self.monomask,line,1)
3050
+           else:
3051
+               break
3052
+           
3053
+       # Protect macros
3054
+       while regex['macros'].search(line):
3055
+           txt = regex['macros'].search(line).group()
3056
+           self.macrobank.append(txt)
3057
+           line = regex['macros'].sub(self.macromask,line,1)
3058
+       
3059
+       # Protect TOC location
3060
+       while regex['toc'].search(line):
3061
+           line = regex['toc'].sub(self.tocmask,line)
3062
+           AUTOTOC = 0
3063
+       
3064
+       # Protect URLs and emails
3065
+       while regex['linkmark'].search(line) or \
3066
+             regex['link'    ].search(line):
3067
+           
3068
+           # Try to match plain or named links
3069
+           match_link  = regex['link'].search(line)
3070
+           match_named = regex['linkmark'].search(line)
3071
+           
3072
+           # Define the current match
3073
+           if match_link and match_named:
3074
+               # Both types found, which is the first?
3075
+               m = match_link
3076
+               if match_named.start() < match_link.start():
3077
+                   m = match_named
3078
+           else:
3079
+               # Just one type found, we're fine
3080
+               m = match_link or match_named
3081
+           
3082
+           # Extract link data and apply mask
3083
+           if m == match_link:              # plain link
3084
+               link = m.group()
3085
+               label = ''
3086
+               link_re = regex['link']
3087
+           else:                            # named link
3088
+               link = m.group('link')
3089
+               label = m.group('label').rstrip()
3090
+               link_re = regex['linkmark']
3091
+           line = link_re.sub(self.linkmask,line,1)
3092
+           
3093
+           # Save link data to the link bank
3094
+           self.linkbank.append((label, link))
3095
+       return line
3096
+   
3097
+   def undo(self, line):
3098
+       
3099
+       # url & email
3100
+       for label,url in self.linkbank:
3101
+           link = get_tagged_link(label, url)
3102
+           line = line.replace(self.linkmask, link, 1)
3103
+       
3104
+       # Expand macros
3105
+       for macro in self.macrobank:
3106
+           macro = self.macroman.expand(macro)
3107
+           line = line.replace(self.macromask, macro, 1)
3108
+       
3109
+       # Expand verb
3110
+       for mono in self.monobank:
3111
+           open_,close = TAGS['fontMonoOpen'],TAGS['fontMonoClose']
3112
+           line = line.replace(self.monomask, open_+mono+close, 1)
3113
+       
3114
+       # Expand raw
3115
+       for raw in self.rawbank:
3116
+           line = line.replace(self.rawmask, raw, 1)
3117
+
3118
+       # Expand tagged
3119
+       for tagged in self.taggedbank:
3120
+           line = line.replace(self.taggedmask, tagged, 1)
3121
+       
3122
+       return line
3123
+
3124
+
3125
+##############################################################################
3126
+
3127
+
3128
+class TitleMaster:
3129
+   "Title things"
3130
+   def __init__(self):
3131
+       self.count = ['',0,0,0,0,0]
3132
+       self.toc   = []
3133
+       self.level = 0
3134
+       self.kind  = ''
3135
+       self.txt   = ''
3136
+       self.label = ''
3137
+       self.tag   = ''
3138
+       self.tag_hold = []
3139
+       self.last_level = 0
3140
+       self.count_id = ''
3141
+       self.user_labels = {}
3142
+       self.anchor_count = 0
3143
+       self.anchor_prefix = 'toc'
3144
+   
3145
+   def _open_close_blocks(self):
3146
+       "Open new title blocks, closing the previous (if any)"
3147
+       if not rules['titleblocks']: return
3148
+       tag = ''
3149
+       last = self.last_level
3150
+       curr = self.level
3151
+       
3152
+       # Same level, just close the previous
3153
+       if curr == last:
3154
+           tag = TAGS.get('title%dClose'%last)
3155
+           if tag: self.tag_hold.append(tag)
3156
+       
3157
+       # Section -> subsection, more depth
3158
+       while curr > last:
3159
+           last += 1
3160
+           
3161
+           # Open the new block of subsections
3162
+           tag = TAGS.get('blockTitle%dOpen'%last)
3163
+           if tag: self.tag_hold.append(tag)
3164
+           
3165
+           # Jump from title1 to title3 or more
3166
+           # Fill the gap with an empty section
3167
+           if curr - last > 0:
3168
+               tag = TAGS.get('title%dOpen'%last)
3169
+               tag = regex['x'].sub('', tag)      # del \a
3170
+               if tag: self.tag_hold.append(tag)
3171
+       
3172
+       # Section <- subsection, less depth
3173
+       while curr < last:
3174
+           # Close the current opened subsection
3175
+           tag = TAGS.get('title%dClose'%last)
3176
+           if tag: self.tag_hold.append(tag)
3177
+           
3178
+           # Close the current opened block of subsections
3179
+           tag = TAGS.get('blockTitle%dClose'%last)
3180
+           if tag: self.tag_hold.append(tag)
3181
+           
3182
+           last -= 1
3183
+           
3184
+           # Close the previous section of the same level
3185
+           # The subsections were under it
3186
+           if curr == last:
3187
+               tag = TAGS.get('title%dClose'%last)
3188
+               if tag: self.tag_hold.append(tag)
3189
+   
3190
+   def add(self, line):
3191
+       "Parses a new title line."
3192
+       if not line: return
3193
+       self._set_prop(line)
3194
+       self._open_close_blocks()
3195
+       self._set_count_id()
3196
+       self._set_label()
3197
+       self._save_toc_info()
3198
+   
3199
+   def close_all(self):
3200
+       "Closes all opened title blocks"
3201
+       ret = []
3202
+       ret.extend(self.tag_hold)
3203
+       while self.level:
3204
+           tag = TAGS.get('title%dClose'%self.level)
3205
+           if tag: ret.append(tag)
3206
+           tag = TAGS.get('blockTitle%dClose'%self.level)
3207
+           if tag: ret.append(tag)
3208
+           self.level -= 1
3209
+       return ret
3210
+   
3211
+   def _save_toc_info(self):
3212
+       "Save TOC info, used by self.dump_marked_toc()"
3213
+       self.toc.append((self.level, self.count_id, self.txt, self.label))
3214
+   
3215
+   def _set_prop(self, line=''):
3216
+       "Extract info from original line and set data holders."
3217
+       # Detect title type (numbered or not)
3218
+       id_ = line.lstrip()[0]
3219
+       if   id_ == '=': kind = 'title'
3220
+       elif id_ == '+': kind = 'numtitle'
3221
+       else: Error("Unknown Title ID '%s'"%id_)
3222
+       # Extract line info
3223
+       match = regex[kind].search(line)
3224
+       level = len(match.group('id'))
3225
+       txt   = match.group('txt').strip()
3226
+       label = match.group('label')
3227
+       # Parse info & save
3228
+       if CONF['enum-title']: kind = 'numtitle'  # force
3229
+       if rules['titleblocks']:
3230
+           self.tag = TAGS.get('%s%dOpen'%(kind,level)) or \
3231
+                      TAGS.get('title%dOpen'%level)
3232
+       else:
3233
+           self.tag = TAGS.get(kind+repr(level)) or \
3234
+                      TAGS.get('title'+repr(level))
3235
+       self.last_level = self.level
3236
+       self.kind  = kind
3237
+       self.level = level
3238
+       self.txt   = txt
3239
+       self.label = label
3240
+   
3241
+   def _set_count_id(self):
3242
+       "Compose and save the title count identifier (if needed)."
3243
+       count_id = ''
3244
+       if self.kind == 'numtitle' and not rules['autonumbertitle']:
3245
+           # Manually increase title count
3246
+           self.count[self.level] += 1
3247
+           # Reset sublevels count (if any)
3248
+           max_levels = len(self.count)
3249
+           if self.level < max_levels-1:
3250
+               for i in range(self.level+1, max_levels):
3251
+                   self.count[i] = 0
3252
+           # Compose count id from hierarchy
3253
+           for i in range(self.level):
3254
+               count_id= "%s%d."%(count_id, self.count[i+1])
3255
+       self.count_id = count_id
3256
+   
3257
+   def _set_label(self):
3258
+       "Compose and save title label, used by anchors."
3259
+       # Remove invalid chars from label set by user
3260
+       self.label = re.sub('[^A-Za-z0-9_-]', '', self.label or '')
3261
+       # Generate name as 15 first :alnum: chars
3262
+       #TODO how to translate safely accented chars to plain?
3263
+       #self.label = re.sub('[^A-Za-z0-9]', '', self.txt)[:15]
3264
+       # 'tocN' label - sequential count, ignoring 'toc-level'
3265
+       #self.label = self.anchor_prefix + str(len(self.toc)+1)
3266
+   
3267
+   def _get_tagged_anchor(self):
3268
+       "Return anchor if user defined a label, or TOC is on."
3269
+       ret = ''
3270
+       label = self.label
3271
+       if CONF['toc'] and self.level <= CONF['toc-level']:
3272
+           # This count is needed bcos self.toc stores all
3273
+           # titles, regardless of the 'toc-level' setting,
3274
+           # so we can't use self.toc length to number anchors
3275
+           self.anchor_count += 1
3276
+           # Autonumber label (if needed)
3277
+           label = label or '%s%s' % (self.anchor_prefix, self.anchor_count)
3278
+       if label and TAGS['anchor']:
3279
+           ret = regex['x'].sub(label,TAGS['anchor'])
3280
+       return ret
3281
+   
3282
+   def _get_full_title_text(self):
3283
+       "Returns the full title contents, already escaped."
3284
+       ret = self.txt
3285
+       # Insert count_id (if any) before text
3286
+       if self.count_id:
3287
+           ret = '%s %s'%(self.count_id, ret)
3288
+       # Escape specials
3289
+       ret = doEscape(TARGET, ret)
3290
+       # Same targets needs final escapes on title lines
3291
+       # It's here because there is a 'continue' after title
3292
+       if rules['finalescapetitle']:
3293
+           ret = doFinalEscape(TARGET, ret)
3294
+       return ret
3295
+   
3296
+   def get(self):
3297
+       "Returns the tagged title as a list."
3298
+       global AA_TITLE
3299
+       ret = []
3300
+       
3301
+       # Maybe some anchoring before?
3302
+       anchor = self._get_tagged_anchor()
3303
+       self.tag = regex['_anchor'].sub(anchor, self.tag)
3304
+       
3305
+       ### Compose & escape title text (TOC uses unescaped)
3306
+       full_title = self._get_full_title_text()
3307
+       
3308
+       # Close previous section area
3309
+       ret.extend(self.tag_hold)
3310
+       self.tag_hold = []
3311
+       
3312
+       tagged = regex['x'].sub(full_title, self.tag)
3313
+
3314
+       # Adds "underline" on TXT target
3315
+       if TARGET == 'txt':
3316
+           if BLOCK.count > 1: ret.append('') # blank line before
3317
+           ret.append(tagged)
3318
+           #Can't be used on Python 3 because every string is unicode unless declared as b'non-unicode string. Array of bytes'
3319
+            #It doesn't support 'decode'
3320
+            #
3321
+           # Get the right letter count for UTF
3322
+           #if CONF['encoding'].lower() == 'utf-8':
3323
+           #   i = len(full_title.decode('utf-8'))
3324
+           #else:  
3325
+           i = len(full_title)
3326
+           ret.append(regex['x'].sub('='*i, self.tag))
3327
+       elif TARGET == 'art' and self.level == 1:
3328
+           if CONF['slides'] :
3329
+               AA_TITLE = tagged
3330
+           else :
3331
+               if BLOCK.count > 1: ret.append('') # blank line before
3332
+               ret.extend(aa_box(tagged, CONF['width']))
3333
+       elif TARGET == 'art':
3334
+           level = 'level'+str(self.level)
3335
+           if BLOCK.count > 1: ret.append('') # blank line before
3336
+           ret.append(tagged)
3337
+           ret.append(AA[level] * len(full_title))
3338
+       else:
3339
+           ret.append(tagged)
3340
+       return ret
3341
+   
3342
+   def dump_marked_toc(self, max_level=99):
3343
+       "Dumps all toc itens as a valid t2t-marked list"
3344
+       ret = []
3345
+       toc_count = 1
3346
+       for level, count_id, txt, label in self.toc:
3347
+           if level > max_level: continue   # ignore
3348
+           indent = '  '*level
3349
+           id_txt = ('%s %s'%(count_id, txt)).lstrip()
3350
+           label = label or self.anchor_prefix+repr(toc_count)
3351
+           toc_count += 1
3352
+           
3353
+           # TOC will have crosslinks to anchors
3354
+           if TAGS['anchor']:
3355
+               if CONF['enum-title'] and level == 1:
3356
+                   # 1. [Foo #anchor] is more readable than [1. Foo #anchor] in level 1.
3357
+                   # This is a stoled idea from Windows .CHM help files.
3358
+                   tocitem = '%s+ [""%s"" #%s]' % (indent, txt, label)
3359
+               else:
3360
+                   tocitem = '%s- [""%s"" #%s]' % (indent, id_txt, label)
3361
+
3362
+           # TOC will be plain text (no links)
3363
+           else:
3364
+               if TARGET in ['txt', 'man', 'art']:
3365
+                   # For these, the list is not necessary, just dump the text
3366
+                   tocitem = '%s""%s""' % (indent, id_txt)
3367
+               else:
3368
+                   tocitem = '%s- ""%s""' % (indent, id_txt)
3369
+           ret.append(tocitem)
3370
+       return ret
3371
+
3372
+
3373
+##############################################################################
3374
+
3375
+#TODO check all this table mess
3376
+# It uses parse_row properties for table lines
3377
+# BLOCK.table() replaces the cells by the parsed content
3378
+class TableMaster:
3379
+   def __init__(self, line=''):
3380
+       self.rows      = []
3381
+       self.border    = 0
3382
+       self.align     = 'Left'
3383
+       self.cellalign = []
3384
+       self.colalign  = []
3385
+       self.cellspan  = []
3386
+       if line:
3387
+           prop = self.parse_row(line)
3388
+           self.border    = prop['border']
3389
+           self.align     = prop['align']
3390
+           self.cellalign = prop['cellalign']
3391
+           self.cellspan  = prop['cellspan']
3392
+           self.colalign  = self._get_col_align()
3393
+
3394
+   def _get_col_align(self):
3395
+       colalign = []
3396
+       for cell in range(0,len(self.cellalign)):
3397
+           align = self.cellalign[cell]
3398
+           span  = self.cellspan[cell]
3399
+           colalign.extend([align] * span)
3400
+       return colalign
3401
+
3402
+   def _get_open_tag(self):
3403
+       topen     = TAGS['tableOpen']
3404
+       tborder   = TAGS['_tableBorder']
3405
+       talign    = TAGS['_tableAlign'+self.align]
3406
+       calignsep = TAGS['tableColAlignSep']
3407
+       calign    = ''
3408
+       
3409
+       # The first line defines if table has border or not
3410
+       if not self.border: tborder = ''
3411
+       # Set the columns alignment
3412
+       if rules['tablecellaligntype'] == 'column':
3413
+           calign = [TAGS['_tableColAlign%s'%x] for x in self.colalign]
3414
+           calign = calignsep.join(calign)
3415
+       # Align full table, set border and Column align (if any)
3416
+       topen = regex['_tableAlign'   ].sub(talign , topen)
3417
+       topen = regex['_tableBorder'  ].sub(tborder, topen)
3418
+       topen = regex['_tableColAlign'].sub(calign , topen)
3419
+       # Tex table spec, border or not: {|l|c|r|} , {lcr}
3420
+       if calignsep and not self.border:
3421
+           # Remove cell align separator
3422
+           topen = topen.replace(calignsep, '')
3423
+       return topen
3424
+   
3425
+   def _get_cell_align(self, cells):
3426
+       ret = []
3427
+       for cell in cells:
3428
+           align = 'Left'
3429
+           if cell.strip():
3430
+               if cell[0] == ' ' and cell[-1] == ' ':
3431
+                   align = 'Center'
3432
+               elif cell[0] == ' ':
3433
+                   align = 'Right'
3434
+           ret.append(align)
3435
+       return ret
3436
+   
3437
+   def _get_cell_span(self, cells):
3438
+       ret = []
3439
+       for cell in cells:
3440
+           span = 1
3441
+           m = re.search('\a(\|+)$', cell)
3442
+           if m: span = len(m.group(1))+1
3443
+           ret.append(span)
3444
+       return ret
3445
+   
3446
+   def _tag_cells(self, rowdata):
3447
+       row = []
3448
+       cells  = rowdata['cells']
3449
+       open_   = TAGS['tableCellOpen']
3450
+       close  = TAGS['tableCellClose']
3451
+       sep    = TAGS['tableCellSep']
3452
+       calign    = [TAGS['_tableCellAlign'+x] for x in rowdata['cellalign']]
3453
+       calignsep = TAGS['tableColAlignSep']
3454
+       ncolumns = len(self.colalign)
3455
+
3456
+       # Populate the span and multicol open tags
3457
+       cspan = []
3458
+       multicol = []
3459
+       colindex = 0
3460
+       for cellindex in range(0,len(rowdata['cellspan'])):
3461
+       
3462
+           span = rowdata['cellspan'][cellindex]
3463
+           align = rowdata['cellalign'][cellindex]
3464
+
3465
+           if span > 1:
3466
+               cspan.append(regex['x'].sub(
3467
+               str(span), TAGS['_tableCellColSpan']))
3468
+
3469
+               mcopen = regex['x'].sub(str(span), TAGS['_tableCellMulticolOpen'])
3470
+               multicol.append(mcopen)
3471
+           else:
3472
+               cspan.append('')
3473
+
3474
+               if colindex < ncolumns and align != self.colalign[colindex]:
3475
+                   mcopen = regex['x'].sub('1', TAGS['_tableCellMulticolOpen'])
3476
+                   multicol.append(mcopen)
3477
+               else:
3478
+                   multicol.append('')
3479
+
3480
+           if not self.border:
3481
+               multicol[-1] = multicol[-1].replace(calignsep, '')
3482
+
3483
+           colindex += span
3484
+       
3485
+       # Maybe is it a title row?
3486
+       if rowdata['title']:
3487
+           open_ = TAGS['tableTitleCellOpen']  or open_
3488
+           close = TAGS['tableTitleCellClose'] or close
3489
+           sep   = TAGS['tableTitleCellSep']   or sep
3490
+       
3491
+       # Should we break the line on *each* table cell?
3492
+       if rules['breaktablecell']: close = close+'\n'
3493
+       
3494
+       # Cells pre processing
3495
+       if rules['tablecellstrip']:
3496
+           cells = [x.strip() for x in cells]
3497
+       if rowdata['title'] and rules['tabletitlerowinbold']:
3498
+           cells = [enclose_me('fontBold',x) for x in cells]
3499
+   
3500
+       # Add cell BEGIN/END tags
3501
+       for cell in cells:
3502
+           copen = open_
3503
+           cclose = close
3504
+           # Make sure we will pop from some filled lists
3505
+           # Fixes empty line bug '| |'
3506
+           this_align = this_span = this_mcopen = ''
3507
+           if calign: this_align = calign.pop(0)
3508
+           if cspan : this_span = cspan.pop(0)
3509
+           if multicol: this_mcopen = multicol.pop(0)
3510
+
3511
+           # Insert cell align into open tag (if cell is alignable)
3512
+           if rules['tablecellaligntype'] == 'cell':
3513
+               copen = regex['_tableCellAlign'].sub(
3514
+                   this_align, copen)
3515
+
3516
+           # Insert cell span into open tag (if cell is spannable)
3517
+           if rules['tablecellspannable']:
3518
+               copen = regex['_tableCellColSpan'].sub(
3519
+                   this_span, copen)
3520
+
3521
+           # Use multicol tags instead (if multicol supported, and if
3522
+           # cell has a span or is aligned differently to column)
3523
+           if rules['tablecellmulticol']:
3524
+               if this_mcopen:
3525
+                   copen = regex['_tableColAlign'].sub(this_align, this_mcopen)
3526
+                   cclose = TAGS['_tableCellMulticolClose']
3527
+
3528
+           row.append(copen + cell + cclose)
3529
+       
3530
+       # Maybe there are cell separators?
3531
+       return sep.join(row)
3532
+   
3533
+   def add_row(self, cells):
3534
+       self.rows.append(cells)
3535
+   
3536
+   def parse_row(self, line):
3537
+       # Default table properties
3538
+       ret = {
3539
+           'border':0, 'title':0, 'align':'Left',
3540
+           'cells':[], 'cellalign':[], 'cellspan':[]
3541
+       }
3542
+       # Detect table align (and remove spaces mark)
3543
+       if line[0] == ' ': ret['align'] = 'Center'
3544
+       line = line.lstrip()
3545
+       # Detect title mark
3546
+       if line[1] == '|': ret['title'] = 1
3547
+       # Detect border mark and normalize the EOL
3548
+       m = re.search(' (\|+) *$', line)
3549
+       if m: line = line+' ' ; ret['border'] = 1
3550
+       else: line = line+' | '
3551
+       # Delete table mark
3552
+       line = regex['table'].sub('', line)
3553
+       # Detect colspan  | foo | bar baz |||
3554
+       line = re.sub(' (\|+)\| ', '\a\\1 | ', line)
3555
+       # Split cells (the last is fake)
3556
+       ret['cells'] = line.split(' | ')[:-1]
3557
+       # Find cells span
3558
+       ret['cellspan'] = self._get_cell_span(ret['cells'])
3559
+       # Remove span ID
3560
+       ret['cells'] = [re.sub('\a\|+$','',x) for x in ret['cells']]
3561
+       # Find cells align
3562
+       ret['cellalign'] = self._get_cell_align(ret['cells'])
3563
+       # Hooray!
3564
+       Debug('Table Prop: %s' % ret, 7)
3565
+       return ret
3566
+   
3567
+   def dump(self):
3568
+       open_ = self._get_open_tag()
3569
+       rows  = self.rows
3570
+       close = TAGS['tableClose']
3571
+       
3572
+       rowopen     = TAGS['tableRowOpen']
3573
+       rowclose    = TAGS['tableRowClose']
3574
+       rowsep      = TAGS['tableRowSep']
3575
+       titrowopen  = TAGS['tableTitleRowOpen']  or rowopen
3576
+       titrowclose = TAGS['tableTitleRowClose'] or rowclose
3577
+       
3578
+       if rules['breaktablelineopen']:
3579
+           rowopen = rowopen + '\n'
3580
+           titrowopen = titrowopen + '\n'
3581
+       
3582
+       # Tex gotchas
3583
+       if TARGET == 'tex':
3584
+           if not self.border:
3585
+               rowopen = titrowopen = ''
3586
+           else:
3587
+               close = rowopen + close
3588
+       
3589
+       # Now we tag all the table cells on each row
3590
+       #tagged_cells = map(lambda x: self._tag_cells(x), rows) #!py15
3591
+       tagged_cells = []
3592
+       for cell in rows: tagged_cells.append(self._tag_cells(cell))
3593
+       
3594
+       # Add row separator tags between lines
3595
+       tagged_rows = []
3596
+       if rowsep:
3597
+           #!py15
3598
+           #tagged_rows = map(lambda x:x+rowsep, tagged_cells)
3599
+           for cell in tagged_cells:
3600
+               tagged_rows.append(cell+rowsep)
3601
+           # Remove last rowsep, because the table is over
3602
+           tagged_rows[-1] = tagged_rows[-1].replace(rowsep, '')
3603
+       # Add row BEGIN/END tags for each line
3604
+       else:
3605
+           for rowdata in rows:
3606
+               if rowdata['title']:
3607
+                   o,c = titrowopen, titrowclose
3608
+               else:
3609
+                   o,c = rowopen, rowclose
3610
+               row = tagged_cells.pop(0)
3611
+               tagged_rows.append(o + row + c)
3612
+       
3613
+       # Join the pieces together
3614
+       fulltable = []
3615
+       if open_: fulltable.append(open_)
3616
+       fulltable.extend(tagged_rows)
3617
+       if close: fulltable.append(close)
3618
+
3619
+       return fulltable
3620
+
3621
+
3622
+##############################################################################
3623
+
3624
+
3625
+class BlockMaster:
3626
+   "TIP: use blockin/out to add/del holders"
3627
+   def __init__(self):
3628
+       self.BLK = []
3629
+       self.HLD = []
3630
+       self.PRP = []
3631
+       self.depth = 0
3632
+       self.count = 0
3633
+       self.last = ''
3634
+       self.tableparser = None
3635
+       self.contains = {
3636
+           'para'    :['comment','raw','tagged'],
3637
+           'verb'    :[],
3638
+           'table'   :['comment'],
3639
+           'raw'     :[],
3640
+           'tagged'  :[],
3641
+           'comment' :[],
3642
+           'quote'   :['quote','comment','raw','tagged'],
3643
+           'list'    :['list','numlist','deflist','para','verb','comment','raw','tagged'],
3644
+           'numlist' :['list','numlist','deflist','para','verb','comment','raw','tagged'],
3645
+           'deflist' :['list','numlist','deflist','para','verb','comment','raw','tagged'],
3646
+           'bar'     :[],
3647
+           'title'   :[],
3648
+           'numtitle':[],
3649
+       }
3650
+       self.allblocks = list(self.contains.keys())
3651
+
3652
+       # If one is found inside another, ignore the marks
3653
+       self.exclusive = ['comment','verb','raw','tagged']
3654
+       
3655
+       # May we include bars inside quotes?
3656
+       if rules['barinsidequote']:
3657
+           self.contains['quote'].append('bar')
3658
+   
3659
+   def block(self):
3660
+       if not self.BLK: return ''
3661
+       return self.BLK[-1]
3662
+   
3663
+   def isblock(self, name=''):
3664
+       return self.block() == name
3665
+   
3666
+   def prop(self, key):
3667
+       if not self.PRP: return ''
3668
+       return self.PRP[-1].get(key) or ''
3669
+   
3670
+   def propset(self, key, val):
3671
+       self.PRP[-1][key] = val
3672
+       #Debug('BLOCK prop ++: %s->%s'%(key,repr(val)), 1)
3673
+       #Debug('BLOCK props: %s'%(repr(self.PRP)), 1)
3674
+   
3675
+   def hold(self):
3676
+       if not self.HLD: return []
3677
+       return self.HLD[-1]
3678
+   
3679
+   def holdadd(self, line):
3680
+       if self.block().endswith('list'): line = [line]
3681
+       self.HLD[-1].append(line)
3682
+       Debug('HOLD add: %s'%repr(line), 4)
3683
+       Debug('FULL HOLD: %s'%self.HLD, 4)
3684
+   
3685
+   def holdaddsub(self, line):
3686
+       self.HLD[-1][-1].append(line)
3687
+       Debug('HOLD addsub: %s'%repr(line), 4)
3688
+       Debug('FULL HOLD: %s'%self.HLD, 4)
3689
+   
3690
+   def holdextend(self, lines):
3691
+       if self.block().endswith('list'): lines = [lines]
3692
+       self.HLD[-1].extend(lines)
3693
+       Debug('HOLD extend: %s'%repr(lines), 4)
3694
+       Debug('FULL HOLD: %s'%self.HLD, 4)
3695
+   
3696
+   def blockin(self, block):
3697
+       ret = []
3698
+       if block not in self.allblocks:
3699
+           Error("Invalid block '%s'"%block)
3700
+
3701
+       # First, let's close other possible open blocks
3702
+       while self.block() and block not in self.contains[self.block()]:
3703
+           ret.extend(self.blockout())
3704
+
3705
+       # Now we can gladly add this new one
3706
+       self.BLK.append(block)
3707
+       self.HLD.append([])
3708
+       self.PRP.append({})
3709
+       self.count += 1
3710
+       if block == 'table': self.tableparser = TableMaster()
3711
+       # Deeper and deeper
3712
+       self.depth = len(self.BLK)
3713
+       Debug('block ++ (%s): %s' % (block,self.BLK), 3)
3714
+       return ret
3715
+   
3716
+   def blockout(self):
3717
+       global AA_COUNT
3718
+                
3719
+       if not self.BLK: Error('No block to pop')
3720
+       blockname = self.BLK.pop()
3721
+       result = getattr(self, blockname)()
3722
+       parsed = self.HLD.pop()
3723
+       self.PRP.pop()
3724
+       self.depth = len(self.BLK)
3725
+       if blockname == 'table': del self.tableparser
3726
+
3727
+       # Inserting a nested block into mother
3728
+       if self.block():
3729
+           if blockname != 'comment': # ignore comment blocks
3730
+               if self.block().endswith('list'):
3731
+                   self.HLD[-1][-1].append(result)
3732
+               else:
3733
+                   self.HLD[-1].append(result)
3734
+           # Reset now. Mother block will have it all
3735
+           result = []
3736
+
3737
+       Debug('block -- (%s): %s' % (blockname,self.BLK), 3)
3738
+       Debug('RELEASED (%s): %s' % (blockname,parsed), 3)
3739
+
3740
+       # Save this top level block name (produced output)
3741
+       # The next block will use it
3742
+       if result:
3743
+           self.last = blockname
3744
+           Debug('BLOCK: %s'%result, 6)
3745
+       
3746
+       # ASCII Art processing
3747
+       if TARGET == 'art' and CONF['slides'] and not CONF['toc-only'] and not CONF.get('art-no-title'):
3748
+           n = (CONF['height'] - 1) - (AA_COUNT % (CONF['height'] - 1) + 1)
3749
+           if n < len(result) and not (TITLE.level == 1 and blockname in ["title", "numtitle"]):
3750
+               result = ([''] * n) + [aa_line(AA['bar1'], CONF['width'])] + aa_slide(AA_TITLE, CONF['width']) + [''] + result
3751
+           if blockname in ["title", "numtitle"] and TITLE.level == 1:
3752
+               aa_title = aa_slide(AA_TITLE, CONF['width']) + ['']
3753
+               if AA_COUNT:
3754
+                   aa_title = ([''] * n) + [aa_line(AA['bar2'], CONF['width'])] + aa_title
3755
+               result = aa_title + result
3756
+           AA_COUNT += len(result)
3757
+
3758
+       return result
3759
+   
3760
+   def _last_escapes(self, line):
3761
+       return doFinalEscape(TARGET, line)
3762
+   
3763
+   def _get_escaped_hold(self):
3764
+       ret = []
3765
+       for line in self.hold():
3766
+           linetype = type(line)
3767
+           if isinstance('', linetype):
3768
+               ret.append(self._last_escapes(line))
3769
+           elif isinstance([], linetype):
3770
+               ret.extend(line)
3771
+           else:
3772
+               Error("BlockMaster: Unknown HOLD item type: %s" % linetype)
3773
+       return ret
3774
+   
3775
+   def _remove_twoblanks(self, lastitem):
3776
+       if len(lastitem) > 1 and lastitem[-2:] == ['','']:
3777
+           return lastitem[:-2]
3778
+       return lastitem
3779
+   
3780
+   def _should_add_blank_line(self, where, blockname):
3781
+       "Validates the blanksaround* rules"
3782
+
3783
+       # Nestable blocks: only mother blocks (level 1) are spaced
3784
+       if blockname.endswith('list') and self.depth > 1:
3785
+           return False
3786
+
3787
+       # The blank line after the block is always added
3788
+       if where == 'after' \
3789
+           and rules['blanksaround'+blockname]:
3790
+           return True
3791
+
3792
+       # # No blank before if it's the first block of the body
3793
+       # elif where == 'before' \
3794
+       #   and BLOCK.count == 1:
3795
+       #   return False
3796
+
3797
+       # # No blank before if it's the first block of this level (nested)
3798
+       # elif where == 'before' \
3799
+       #   and self.count == 1:
3800
+       #   return False
3801
+
3802
+       # The blank line before the block is only added if
3803
+       # the previous block haven't added a blank line
3804
+       # (to avoid consecutive blanks)
3805
+       elif where == 'before' \
3806
+           and rules['blanksaround'+blockname] \
3807
+           and not rules.get('blanksaround'+self.last):
3808
+           return True
3809
+
3810
+       # Nested quotes are handled here,
3811
+       # because the mother quote isn't closed yet
3812
+       elif where == 'before' \
3813
+           and blockname == 'quote' \
3814
+           and rules['blanksaround'+blockname] \
3815
+           and self.depth > 1:
3816
+           return True
3817
+
3818
+       return False
3819
+
3820
+   def comment(self):
3821
+       return ''
3822
+   
3823
+   def raw(self):
3824
+       lines = self.hold()
3825
+       return [doEscape(TARGET, x) for x in lines]
3826
+
3827
+   def tagged(self):
3828
+       return self.hold()
3829
+   
3830
+   def para(self):
3831
+       result = []
3832
+       open_ = TAGS['paragraphOpen']
3833
+       close = TAGS['paragraphClose']
3834
+       lines = self._get_escaped_hold()
3835
+
3836
+       # Blank line before?
3837
+       if self._should_add_blank_line('before', 'para'): result.append('')
3838
+
3839
+       # Open tag
3840
+       if open_: result.append(open_)
3841
+
3842
+       # Pagemaker likes a paragraph as a single long line
3843
+       if rules['onelinepara']:
3844
+           result.append(' '.join(lines))
3845
+       # Others are normal :)
3846
+       else:
3847
+           result.extend(lines)
3848
+
3849
+       # Close tag
3850
+       if close: result.append(close)
3851
+
3852
+       # Blank line after?
3853
+       if self._should_add_blank_line('after', 'para'): result.append('')
3854
+   
3855
+       # Very very very very very very very very very UGLY fix
3856
+       # Needed because <center> can't appear inside <p>
3857
+       try:
3858
+           if len(lines) == 1 and \
3859
+              TARGET in ('html', 'xhtml') and \
3860
+              re.match('^\s*<center>.*</center>\s*$', lines[0]):
3861
+               result = [lines[0]]
3862
+       except: pass
3863
+       
3864
+       return result
3865
+   
3866
+   def verb(self):
3867
+       "Verbatim lines are not masked, so there's no need to unmask"
3868
+       result = []
3869
+       open_ = TAGS['blockVerbOpen']
3870
+       close = TAGS['blockVerbClose']
3871
+
3872
+       # Blank line before?
3873
+       if self._should_add_blank_line('before', 'verb'): result.append('')
3874
+
3875
+       # Open tag
3876
+       if open_: result.append(open_)
3877
+
3878
+       # Get contents
3879
+       for line in self.hold():
3880
+           if self.prop('mapped') == 'table':
3881
+               line = MacroMaster().expand(line)
3882
+           if not rules['verbblocknotescaped']:
3883
+               line = doEscape(TARGET,line)
3884
+           if rules['indentverbblock']:
3885
+               line = '  '+line
3886
+           if rules['verbblockfinalescape']:
3887
+               line = doFinalEscape(TARGET, line)
3888
+           result.append(line)
3889
+
3890
+       # Close tag
3891
+       if close: result.append(close)
3892
+
3893
+       # Blank line after?
3894
+       if self._should_add_blank_line('after', 'verb'): result.append('')
3895
+
3896
+       return result
3897
+
3898
+   def numtitle(self): return self.title('numtitle')
3899
+   def title(self, name='title'):
3900
+       result = []
3901
+
3902
+       # Blank line before?
3903
+       if self._should_add_blank_line('before', name): result.append('')
3904
+
3905
+       # Get contents
3906
+       result.extend(TITLE.get())
3907
+
3908
+       # Blank line after?
3909
+       if self._should_add_blank_line('after', name): result.append('')
3910
+
3911
+       return result
3912
+
3913
+   def table(self):
3914
+       result = []
3915
+
3916
+       # Blank line before?
3917
+       if self._should_add_blank_line('before', 'table'): result.append('')
3918
+
3919
+       # Rewrite all table cells by the unmasked and escaped data
3920
+       lines = self._get_escaped_hold()
3921
+       for i in range(len(lines)):
3922
+           cells = lines[i].split(SEPARATOR)
3923
+           self.tableparser.rows[i]['cells'] = cells
3924
+       result.extend(self.tableparser.dump())
3925
+
3926
+       # Blank line after?
3927
+       if self._should_add_blank_line('after', 'table'): result.append('')
3928
+
3929
+       return result
3930
+
3931
+   def quote(self):
3932
+       result = []
3933
+       open_  = TAGS['blockQuoteOpen']            # block based
3934
+       close  = TAGS['blockQuoteClose']
3935
+       qline  = TAGS['blockQuoteLine']            # line based
3936
+       indent = tagindent = '\t'*self.depth
3937
+       
3938
+       # Apply rules
3939
+       if rules['tagnotindentable']: tagindent = ''
3940
+       if not rules['keepquoteindent']: indent = ''
3941
+       
3942
+       # Blank line before?
3943
+       if self._should_add_blank_line('before', 'quote'): result.append('')
3944
+
3945
+       # Open tag
3946
+       if open_: result.append(tagindent+open_)
3947
+       
3948
+       # Get contents
3949
+       for item in self.hold():
3950
+           if isinstance(item, type([])):
3951
+               result.extend(item)        # subquotes
3952
+           else:
3953
+               item = regex['quote'].sub('', item)  # del TABs
3954
+               item = self._last_escapes(item)
3955
+               item = qline*self.depth + item
3956
+               result.append(indent+item) # quote line
3957
+
3958
+       # Close tag
3959
+       if close: result.append(tagindent+close)
3960
+
3961
+       # Blank line after?
3962
+       if self._should_add_blank_line('after', 'quote'): result.append('')
3963
+       
3964
+       return result
3965
+   
3966
+   def bar(self):
3967
+       result = []
3968
+       bar_tag = ''
3969
+
3970
+       # Blank line before?
3971
+       if self._should_add_blank_line('before', 'bar'): result.append('')
3972
+
3973
+       # Get the original bar chars
3974
+       bar_chars = self.hold()[0].strip()
3975
+
3976
+       # Set bar type
3977
+       if bar_chars.startswith('='): bar_tag = TAGS['bar2']
3978
+       else                        : bar_tag = TAGS['bar1']
3979
+
3980
+       # To avoid comment tag confusion like <!-- ------ --> (sgml)
3981
+       if TAGS['comment'].count('--'):
3982
+           bar_chars = bar_chars.replace('--', '__')
3983
+
3984
+       # Get the bar tag (may contain \a)
3985
+       result.append(regex['x'].sub(bar_chars, bar_tag))
3986
+
3987
+       # Blank line after?
3988
+       if self._should_add_blank_line('after', 'bar'): result.append('')
3989
+
3990
+       return result
3991
+
3992
+   def deflist(self): return self.list('deflist')
3993
+   def numlist(self): return self.list('numlist')
3994
+   def list(self, name='list'):
3995
+       result    = []
3996
+       items     = self.hold()
3997
+       indent    = self.prop('indent')
3998
+       tagindent = indent
3999
+       listline  = TAGS.get(name+'ItemLine')
4000
+       itemcount = 0
4001
+
4002
+       if name == 'deflist':
4003
+           itemopen  = TAGS[name+'Item1Open']
4004
+           itemclose = TAGS[name+'Item2Close']
4005
+           itemsep   = TAGS[name+'Item1Close']+\
4006
+                       TAGS[name+'Item2Open']
4007
+       else:
4008
+           itemopen  = TAGS[name+'ItemOpen']
4009
+           itemclose = TAGS[name+'ItemClose']
4010
+           itemsep   = ''
4011
+       
4012
+       # Apply rules
4013
+       if rules['tagnotindentable']: tagindent = ''
4014
+       if not rules['keeplistindent']: indent = tagindent = ''
4015
+
4016
+       # ItemLine: number of leading chars identifies list depth
4017
+       if listline:
4018
+           itemopen  = listline*self.depth + itemopen
4019
+       
4020
+       # Adds trailing space on opening tags
4021
+       if (name == 'list'    and rules['spacedlistitemopen']) or \
4022
+          (name == 'numlist' and rules['spacednumlistitemopen']):
4023
+           itemopen = itemopen + ' '
4024
+           
4025
+       # Remove two-blanks from list ending mark, to avoid <p>
4026
+       items[-1] = self._remove_twoblanks(items[-1])
4027
+
4028
+       # Blank line before?
4029
+       if self._should_add_blank_line('before', name): result.append('')
4030
+
4031
+       # Tag each list item (multiline items), store in listbody
4032
+       itemopenorig = itemopen
4033
+       listbody = []
4034
+       widelist = 0
4035
+       for item in items:
4036
+           
4037
+           # Add "manual" item count for noautonum targets
4038
+           itemcount += 1
4039
+           if name == 'numlist' and not rules['autonumberlist']:
4040
+               n = str(itemcount)
4041
+               itemopen = regex['x'].sub(n, itemopenorig)
4042
+               del n
4043
+
4044
+           # Tag it
4045
+           item[0] = self._last_escapes(item[0])
4046
+           if name == 'deflist':
4047
+               z,term,rest = item[0].split(SEPARATOR, 2)
4048
+               item[0] = rest
4049
+               if not item[0]: del item[0]      # to avoid <p>
4050
+               listbody.append(tagindent+itemopen+term+itemsep)
4051
+           else:
4052
+               fullitem = tagindent+itemopen
4053
+               listbody.append(item[0].replace(SEPARATOR, fullitem))
4054
+               del item[0]
4055
+           
4056
+           # Process next lines for this item (if any)
4057
+           for line in item:
4058
+               if isinstance(line, type([])): # sublist inside
4059
+                   listbody.extend(line)
4060
+               else:
4061
+                   line = self._last_escapes(line)
4062
+                   
4063
+                   # Blank lines turns to <p>
4064
+                   if not line and rules['parainsidelist']:
4065
+                       line = indent + TAGS['paragraphOpen'] + TAGS['paragraphClose']
4066
+                       line = line.rstrip()
4067
+                       widelist = 1
4068
+                       
4069
+                   # Some targets don't like identation here (wiki)
4070
+                   if not rules['keeplistindent'] or (name == 'deflist' and rules['deflisttextstrip']):
4071
+                       line = line.lstrip()
4072
+
4073
+                   # Maybe we have a line prefix to add? (wiki)
4074
+                   if name == 'deflist' and TAGS['deflistItem2LinePrefix']:
4075
+                       line = TAGS['deflistItem2LinePrefix'] + line
4076
+                       
4077
+                   listbody.append(line)
4078
+           
4079
+           # Close item (if needed)
4080
+           if itemclose: listbody.append(tagindent+itemclose)
4081
+       
4082
+       if not widelist and rules['compactlist']:
4083
+           listopen = TAGS.get(name+'OpenCompact')
4084
+           listclose = TAGS.get(name+'CloseCompact')
4085
+       else:
4086
+           listopen  = TAGS.get(name+'Open')
4087
+           listclose = TAGS.get(name+'Close')
4088
+
4089
+       # Open list (not nestable lists are only opened at mother)
4090
+       if listopen and not \
4091
+          (rules['listnotnested'] and BLOCK.depth != 1):
4092
+           result.append(tagindent+listopen)
4093
+
4094
+       result.extend(listbody)
4095
+       
4096
+       # Close list (not nestable lists are only closed at mother)
4097
+       if listclose and not \
4098
+          (rules['listnotnested'] and self.depth != 1):
4099
+           result.append(tagindent+listclose)
4100
+
4101
+       # Blank line after?
4102
+       if self._should_add_blank_line('after', name): result.append('')
4103
+
4104
+       return result
4105
+
4106
+
4107
+##############################################################################
4108
+
4109
+
4110
+class MacroMaster:
4111
+   def __init__(self, config={}):
4112
+       self.name     = ''
4113
+       self.config   = config or CONF
4114
+       self.infile   = self.config['sourcefile']
4115
+       self.outfile  = self.config['outfile']
4116
+       self.currdate = time.localtime(time.time())
4117
+       self.rgx      = regex.get('macros') or getRegexes()['macros']
4118
+       self.fileinfo = { 'infile': None, 'outfile': None }
4119
+       self.dft_fmt  = MACROS
4120
+   
4121
+   def walk_file_format(self, fmt):
4122
+       "Walks the %%{in/out}file format string, expanding the % flags"
4123
+       i = 0; ret = ''                                 # counter/hold
4124
+       while i < len(fmt):                             # char by char
4125
+           c = fmt[i]; i += 1
4126
+           if c == '%':                            # hot char!
4127
+               if i == len(fmt):               # % at the end
4128
+                   ret = ret + c
4129
+                   break
4130
+               c = fmt[i]; i += 1              # read next
4131
+               ret = ret + self.expand_file_flag(c)
4132
+           else:
4133
+               ret = ret +c                    # common char
4134
+       return ret
4135
+   
4136
+   def expand_file_flag(self, flag):
4137
+       "%f: filename          %F: filename (w/o extension)"
4138
+       "%d: dirname           %D: dirname (only parent dir)"
4139
+       "%p: file path         %e: extension"
4140
+       info = self.fileinfo[self.name]           # get dict
4141
+       if   flag == '%': x = '%'                 # %% -> %
4142
+       elif flag == 'f': x = info['name']
4143
+       elif flag == 'F': x = re.sub('\.[^.]*$','',info['name'])
4144
+       elif flag == 'd': x = info['dir']
4145
+       elif flag == 'D': x = os.path.split(info['dir'])[-1]
4146
+       elif flag == 'p': x = info['path']
4147
+       elif flag == 'e': x = re.search('.(\.([^.]+))?$', info['name']).group(2) or ''
4148
+       #TODO simpler way for %e ?
4149
+       else            : x = '%'+flag            # false alarm
4150
+       return x
4151
+   
4152
+   def set_file_info(self, macroname):
4153
+       if self.fileinfo.get(macroname): return   # already done
4154
+       file_ = getattr(self, self.name)           # self.infile
4155
+       if file_ == STDOUT or file_ == MODULEOUT:
4156
+           dir_ = ''
4157
+           path = name = file_
4158
+       else:
4159
+           path = os.path.abspath(file_)
4160
+           dir_ = os.path.dirname(path)
4161
+           name = os.path.basename(path)
4162
+       self.fileinfo[macroname] = {'path':path,'dir':dir_,'name':name}
4163
+   
4164
+   def expand(self, line=''):
4165
+       "Expand all macros found on the line"
4166
+       while self.rgx.search(line):
4167
+           m = self.rgx.search(line)
4168
+           name = self.name = m.group('name').lower()
4169
+           fmt = m.group('fmt') or self.dft_fmt.get(name)
4170
+           if name == 'date':
4171
+               txt = time.strftime(fmt,self.currdate)
4172
+           elif name == 'mtime':
4173
+               if self.infile in (STDIN, MODULEIN):
4174
+                   fdate = self.currdate
4175
+               else:
4176
+                   mtime = os.path.getmtime(self.infile)
4177
+                   fdate = time.localtime(mtime)
4178
+               txt = time.strftime(fmt,fdate)
4179
+           elif name == 'infile' or name == 'outfile':
4180
+               self.set_file_info(name)
4181
+               txt = self.walk_file_format(fmt)
4182
+           else:
4183
+               Error("Unknown macro name '%s'"%name)
4184
+           line = self.rgx.sub(txt,line,1)
4185
+       return line
4186
+
4187
+
4188
+##############################################################################
4189
+
4190
+
4191
+def listTargets():
4192
+   """list all available targets"""
4193
+   targets = sorted(TARGETS)
4194
+   for target in targets:
4195
+       print("%s\t%s" % (target, TARGET_NAMES.get(target)))
4196
+
4197
+def dumpConfig(source_raw, parsed_config):
4198
+   onoff = {1:_('ON'), 0:_('OFF')}
4199
+   data = [
4200
+       (_('RC file')        , RC_RAW     ),
4201
+       (_('source document'), source_raw ),
4202
+       (_('command line')   , CMDLINE_RAW)
4203
+   ]
4204
+   # First show all RAW data found
4205
+   for label, cfg in data:
4206
+       print(_('RAW config for %s')%label)
4207
+       for target,key,val in cfg:
4208
+           target = '(%s)'%target
4209
+           key    = dotted_spaces("%-14s"%key)
4210
+           val    = val or _('ON')
4211
+           print('  %-8s %s: %s'%(target,key,val))
4212
+       print()
4213
+   # Then the parsed results of all of them
4214
+   print(_('Full PARSED config'))
4215
+   for key in sorted( parsed_config.keys() ):
4216
+       val = parsed_config[key]
4217
+       # Filters are the last
4218
+       if key == 'preproc' or key == 'postproc':
4219
+           continue
4220
+       # Flag beautifier
4221
+       if key in FLAGS.keys() or key in ACTIONS.keys():
4222
+           val = onoff.get(val) or val
4223
+       # List beautifier
4224
+       if isinstance(val, type([])):
4225
+           if key == 'options': sep = ' '
4226
+           else               : sep = ', '
4227
+           val = sep.join(val)
4228
+       print("%25s: %s"%(dotted_spaces("%-14s"%key),val))
4229
+   print()
4230
+   print(_('Active filters'))
4231
+   for filter_ in ['preproc', 'postproc']:
4232
+       for rule in parsed_config.get(filter_) or []:
4233
+           print("%25s: %s  ->  %s" % (
4234
+               dotted_spaces("%-14s"%filter_), rule[0], rule[1]))
4235
+
4236
+
4237
+def get_file_body(file_):
4238
+   "Returns all the document BODY lines"
4239
+   return process_source_file(file_, noconf=1)[1][2]
4240
+
4241
+
4242
+def finish_him(outlist, config):
4243
+   "Writing output to screen or file"
4244
+   outfile = config['outfile']
4245
+   outlist = unmaskEscapeChar(outlist)
4246
+   outlist = expandLineBreaks(outlist)
4247
+   
4248
+   # Apply PostProc filters
4249
+   if config['postproc']:
4250
+       filters = compile_filters(config['postproc'],
4251
+           _('Invalid PostProc filter regex'))
4252
+       postoutlist = []
4253
+       errmsg = _('Invalid PostProc filter replacement')
4254
+       for line in outlist:
4255
+           for rgx,repl in filters:
4256
+               try: line = rgx.sub(repl, line)
4257
+               except: Error("%s: '%s'"%(errmsg, repl))
4258
+           postoutlist.append(line)
4259
+       outlist = postoutlist[:]
4260
+   
4261
+   if outfile == MODULEOUT:
4262
+       return outlist
4263
+   elif outfile == STDOUT:
4264
+       if GUI:
4265
+           return outlist, config
4266
+       else:
4267
+           for line in outlist: print(line)
4268
+   else:
4269
+       Savefile(outfile, addLineBreaks(outlist))
4270
+       if not GUI and not QUIET:
4271
+           print(_('%s wrote %s')%(my_name,outfile))
4272
+   
4273
+   if config['split']:
4274
+       if not QUIET: print("--- html...")
4275
+       sgml2html = 'sgml2html -s %s -l %s %s' % (
4276
+           config['split'], config['lang'] or lang, outfile)
4277
+       if not QUIET: print("Running system command:", sgml2html)
4278
+       os.system(sgml2html)
4279
+
4280
+
4281
+def toc_inside_body(body, toc, config):
4282
+   ret = []
4283
+   if AUTOTOC: return body                     # nothing to expand
4284
+   toc_mark = MaskMaster().tocmask
4285
+   # Expand toc mark with TOC contents
4286
+   for line in body:
4287
+       if line.count(toc_mark):            # toc mark found
4288
+           if config['toc']:
4289
+               ret.extend(toc)     # include if --toc
4290
+           else:
4291
+               pass                # or remove %%toc line
4292
+       else:
4293
+           ret.append(line)            # common line
4294
+   return ret
4295
+
4296
+def toc_tagger(toc, config):
4297
+   "Returns the tagged TOC, as a single tag or a tagged list"
4298
+   ret = []
4299
+   # Convert the TOC list (t2t-marked) to the target's list format
4300
+   if config['toc-only'] or (config['toc'] and not TAGS['TOC']):
4301
+       fakeconf = config.copy()
4302
+       fakeconf['headers']    = 0
4303
+       fakeconf['toc-only']   = 0
4304
+       fakeconf['mask-email'] = 0
4305
+       fakeconf['preproc']    = []
4306
+       fakeconf['postproc']   = []
4307
+       fakeconf['css-sugar']  = 0
4308
+       fakeconf['art-no-title']  = 1  # needed for --toc and --slides together, avoids slide title before TOC
4309
+       ret,foo = convert(toc, fakeconf)
4310
+       set_global_config(config)   # restore config
4311
+   # Our TOC list is not needed, the target already knows how to do a TOC
4312
+   elif config['toc'] and TAGS['TOC']:
4313
+       ret = [TAGS['TOC']]
4314
+   return ret
4315
+
4316
+def toc_formatter(toc, config):
4317
+   "Formats TOC for automatic placement between headers and body"
4318
+
4319
+   if config['toc-only']: return toc              # no formatting needed
4320
+   if not config['toc'] : return []               # TOC disabled
4321
+   ret = toc
4322
+
4323
+   # Art: An automatic "Table of Contents" header is added to the TOC slide
4324
+   if config['target'] == 'art' and config['slides']:
4325
+       n = (config['height'] - 1) - (len(toc) + 6) % (config['height'] - 1)
4326
+       toc = aa_slide(_("Table of Contents"), config['width']) + toc + ([''] * n)
4327
+       toc.append(aa_line(AA['bar2'], config['width']))
4328
+       return toc
4329
+
4330
+   # TOC open/close tags (if any)
4331
+   if TAGS['tocOpen' ]: ret.insert(0, TAGS['tocOpen'])
4332
+   if TAGS['tocClose']: ret.append(TAGS['tocClose'])
4333
+
4334
+   # Autotoc specific formatting
4335
+   if AUTOTOC:
4336
+       if rules['autotocwithbars']:           # TOC between bars
4337
+           para = TAGS['paragraphOpen']+TAGS['paragraphClose']
4338
+           bar  = regex['x'].sub('-' * DFT_TEXT_WIDTH, TAGS['bar1'])
4339
+           tocbar = [para, bar, para]
4340
+           if config['target'] == 'art' and config['headers']:
4341
+               # exception: header already printed a bar
4342
+               ret = [para] + ret + tocbar
4343
+           else:
4344
+               ret = tocbar + ret + tocbar
4345
+       if rules['blankendautotoc']:           # blank line after TOC
4346
+           ret.append('')
4347
+       if rules['autotocnewpagebefore']:      # page break before TOC
4348
+           ret.insert(0,TAGS['pageBreak'])
4349
+       if rules['autotocnewpageafter']:       # page break after TOC
4350
+           ret.append(TAGS['pageBreak'])
4351
+   return ret
4352
+
4353
+
4354
+def doHeader(headers, config):
4355
+   if not config['headers']: return []
4356
+   if not headers: headers = ['','','']
4357
+   target = config['target']
4358
+   if target not in HEADER_TEMPLATE:
4359
+       Error("doHeader: Unknown target '%s'"%target)
4360
+   
4361
+   if target in ('html','xhtml') and config.get('css-sugar'):
4362
+       template = HEADER_TEMPLATE[target+'css'].split('\n')
4363
+   else:
4364
+       template = HEADER_TEMPLATE[target].split('\n')
4365
+   
4366
+   head_data = {'STYLE':[], 'ENCODING':''}
4367
+   for key in head_data.keys():
4368
+       val = config.get(key.lower())
4369
+       # Remove .sty extension from each style filename (freaking tex)
4370
+       # XXX Can't handle --style foo.sty,bar.sty
4371
+       if target == 'tex' and key == 'STYLE':
4372
+           val = [re.sub('(?i)\.sty$','',x) for x in val]
4373
+       if key == 'ENCODING':
4374
+           val = get_encoding_string(val, target)
4375
+       head_data[key] = val
4376
+   # Parse header contents
4377
+   for i in 0,1,2:
4378
+       # Expand macros
4379
+       contents = MacroMaster(config=config).expand(headers[i])
4380
+       # Escapes - on tex, just do it if any \tag{} present
4381
+       if target != 'tex' or \
4382
+         (target == 'tex' and re.search(r'\\\w+{', contents)):
4383
+           contents = doEscape(target, contents)
4384
+       if target == 'lout':
4385
+           contents = doFinalEscape(target, contents)
4386
+       
4387
+       head_data['HEADER%d'%(i+1)] = contents
4388
+
4389
+   # css-inside removes STYLE line
4390
+   #XXX In tex, this also removes the modules call (%!style:amsfonts)
4391
+   if target in ('html','xhtml') and config.get('css-inside') and \
4392
+      config.get('style'):
4393
+       head_data['STYLE'] = []
4394
+
4395
+   Debug("Header Data: %s"%head_data, 1)
4396
+
4397
+   # ASCII Art does not use a header template, aa_header() formats the header
4398
+   if target == 'art':
4399
+                n_h = len([v for v in head_data if v.startswith("HEADER") and head_data[v]])
4400
+                if not n_h :
4401
+                        return []
4402
+                if config['slides']:
4403
+                        x = config['height'] - 3 - (n_h * 3)
4404
+                        n = x / (n_h + 1)
4405
+                        end = x % (n_h + 1)
4406
+                        template = aa_header(head_data, config['width'], n, end)
4407
+                else:
4408
+                        template = [''] + aa_header(head_data, config['width'], 2, 0)
4409
+       # Header done, let's get out
4410
+                return template
4411
+
4412
+   # Scan for empty dictionary keys
4413
+   # If found, scan template lines for that key reference
4414
+   # If found, remove the reference
4415
+   # If there isn't any other key reference on the same line, remove it
4416
+   #TODO loop by template line > key
4417
+   for key in head_data.keys():
4418
+       if head_data.get(key): continue
4419
+       for line in template:
4420
+           if line.count('%%(%s)s'%key):
4421
+               sline = line.replace('%%(%s)s'%key, '')
4422
+               if not re.search(r'%\([A-Z0-9]+\)s', sline):
4423
+                   template.remove(line)
4424
+   # Style is a multiple tag.
4425
+   # - If none or just one, use default template
4426
+   # - If two or more, insert extra lines in a loop (and remove original)
4427
+   styles = head_data['STYLE']
4428
+   if len(styles) == 1:
4429
+       head_data['STYLE'] = styles[0]
4430
+   elif len(styles) > 1:
4431
+       style_mark = '%(STYLE)s'
4432
+       for i in range(len(template)):
4433
+           if template[i].count(style_mark):
4434
+               while styles:
4435
+                   template.insert(i+1, template[i].replace(style_mark, styles.pop()))
4436
+               del template[i]
4437
+               break
4438
+   # Populate template with data (dict expansion)
4439
+   template = '\n'.join(template) % head_data
4440
+   
4441
+   # Adding CSS contents into template (for --css-inside)
4442
+   # This code sux. Dirty++
4443
+   if target in ('html','xhtml') and config.get('css-inside') and \
4444
+      config.get('style'):
4445
+       set_global_config(config) # usually on convert(), needed here
4446
+       for i in range(len(config['style'])):
4447
+           cssfile = config['style'][i]
4448
+           if not os.path.isabs(cssfile):
4449
+               infile = config.get('sourcefile')
4450
+               cssfile = os.path.join(
4451
+                   os.path.dirname(infile), cssfile)
4452
+           try:
4453
+               contents = Readfile(cssfile, 1)
4454
+               css = "\n%s\n%s\n%s\n%s\n" % (
4455
+                   doCommentLine("Included %s" % cssfile),
4456
+                   TAGS['cssOpen'],
4457
+                   '\n'.join(contents),
4458
+                   TAGS['cssClose'])
4459
+               # Style now is content, needs escaping (tex)
4460
+               #css = maskEscapeChar(css)
4461
+           except:
4462
+               errmsg = "CSS include failed for %s" % cssfile
4463
+               css = "\n%s\n" % (doCommentLine(errmsg))
4464
+           # Insert this CSS file contents on the template
4465
+           template = re.sub('(?i)(</HEAD>)', css+r'\1', template)
4466
+           # template = re.sub(r'(?i)(\\begin{document})',
4467
+           #       css+'\n'+r'\1', template) # tex
4468
+       
4469
+       # The last blank line to keep everything separated
4470
+       template = re.sub('(?i)(</HEAD>)', '\n'+r'\1', template)
4471
+   
4472
+   return template.split('\n')
4473
+
4474
+def doCommentLine(txt):
4475
+   # The -- string ends a (h|sg|xht)ml comment :(
4476
+   txt = maskEscapeChar(txt)
4477
+   if TAGS['comment'].count('--') and txt.count('--'):
4478
+       txt = re.sub('-(?=-)', r'-\\', txt)
4479
+   
4480
+   if TAGS['comment']:
4481
+       return regex['x'].sub(txt, TAGS['comment'])
4482
+   return ''
4483
+
4484
+def doFooter(config):
4485
+   ret = []
4486
+
4487
+   # No footer. The --no-headers option hides header AND footer
4488
+   if not config['headers']:
4489
+       return []
4490
+   
4491
+   # Only add blank line before footer if last block doesn't added by itself
4492
+   if not rules.get('blanksaround'+BLOCK.last):
4493
+       ret.append('')
4494
+   
4495
+   # Add txt2tags info at footer, if target supports comments
4496
+   if TAGS['comment']:
4497
+
4498
+       # Not using TARGET_NAMES because it's i18n'ed.
4499
+       # It's best to always present this info in english.
4500
+       target = config['target']
4501
+       if config['target'] == 'tex':
4502
+           target = 'LaTeX2e'
4503
+       
4504
+       t2t_version = '%s code generated by %s %s (%s)' % (target, my_name, my_version, my_url)
4505
+       cmdline = 'cmdline: %s %s' % (my_name, ' '.join(config['realcmdline']))
4506
+
4507
+       ret.append(doCommentLine(t2t_version))
4508
+       ret.append(doCommentLine(cmdline))
4509
+
4510
+   # Maybe we have a specific tag to close the document?
4511
+   if TAGS['EOD']:
4512
+       ret.append(TAGS['EOD'])
4513
+
4514
+   return ret
4515
+
4516
+def doEscape(target,txt):
4517
+   "Target-specific special escapes. Apply *before* insert any tag."
4518
+   tmpmask = 'vvvvThisEscapingSuxvvvv'
4519
+   if target in ('html','sgml','xhtml','dbk'):
4520
+       txt = re.sub('&','&amp;',txt)
4521
+       txt = re.sub('<','&lt;',txt)
4522
+       txt = re.sub('>','&gt;',txt)
4523
+       if target == 'sgml':
4524
+           txt = re.sub('\xff','&yuml;',txt)  # "+y
4525
+   elif target == 'pm6':
4526
+       txt = re.sub('<','<\#60>',txt)
4527
+   elif target == 'mgp':
4528
+       txt = re.sub('^%',' %',txt)  # add leading blank to avoid parse
4529
+   elif target == 'man':
4530
+       txt = re.sub("^([.'])", '\\&\\1',txt)           # command ID
4531
+       txt = txt.replace(ESCCHAR, ESCCHAR+'e')         # \e
4532
+   elif target == 'lout':
4533
+       # TIP: / moved to FinalEscape to avoid //italic//
4534
+       # TIP: these are also converted by lout:  ...  ---  --
4535
+       txt = txt.replace(ESCCHAR, tmpmask)             # \
4536
+       txt = txt.replace('"', '"%s""'%ESCCHAR)         # "\""
4537
+       txt = re.sub('([|&{}@#^~])', '"\\1"', txt)      # "@"
4538
+       txt = txt.replace(tmpmask, '"%s"'%(ESCCHAR*2))  # "\\"
4539
+   elif target == 'tex':
4540
+       # Mark literal \ to be changed to $\backslash$ later
4541
+       txt = txt.replace(ESCCHAR, tmpmask)
4542
+       txt = re.sub('([#$&%{}])', ESCCHAR+r'\1'  , txt)  # \%
4543
+       txt = re.sub('([~^])'    , ESCCHAR+r'\1{}', txt)  # \~{}
4544
+       txt = re.sub('([<|>])'   ,         r'$\1$', txt)  # $>$
4545
+       txt = txt.replace(tmpmask, maskEscapeChar(r'$\backslash$'))
4546
+       # TIP the _ is escaped at the end
4547
+   return txt
4548
+
4549
+# TODO man: where - really needs to be escaped?
4550
+def doFinalEscape(target, txt):
4551
+   "Last escapes of each line"
4552
+   if   target == 'pm6' : txt = txt.replace(ESCCHAR+'<', r'<\#92><')
4553
+   elif target == 'man' : txt = txt.replace('-', r'\-')
4554
+   elif target == 'sgml': txt = txt.replace('[', '&lsqb;')
4555
+   elif target == 'lout': txt = txt.replace('/', '"/"')
4556
+   elif target == 'tex' :
4557
+       txt = txt.replace('_', r'\_')
4558
+       txt = txt.replace('vvvvTexUndervvvv', '_')  # shame!
4559
+   return txt
4560
+
4561
+def EscapeCharHandler(action, data):
4562
+   "Mask/Unmask the Escape Char on the given string"
4563
+   if not data.strip(): return data
4564
+   if action not in ('mask','unmask'):
4565
+       Error("EscapeCharHandler: Invalid action '%s'"%action)
4566
+   if action == 'mask': return data.replace('\\', ESCCHAR)
4567
+   else:                return data.replace(ESCCHAR, '\\')
4568
+
4569
+def maskEscapeChar(data):
4570
+   "Replace any Escape Char \ with a text mask (Input: str or list)"
4571
+   if isinstance(data, type([])):
4572
+       return [EscapeCharHandler('mask', x) for x in data]
4573
+   return EscapeCharHandler('mask',data)
4574
+
4575
+def unmaskEscapeChar(data):
4576
+   "Undo the Escape char \ masking (Input: str or list)"
4577
+   if isinstance(data, type([])):
4578
+       return [EscapeCharHandler('unmask', x) for x in data]
4579
+   return EscapeCharHandler('unmask',data)
4580
+
4581
+def addLineBreaks(mylist):
4582
+   "use LB to respect sys.platform"
4583
+   ret = []
4584
+   for line in mylist:
4585
+       line = line.replace('\n', LB)        # embedded \n's
4586
+       ret.append(line+LB)                  # add final line break
4587
+   return ret
4588
+
4589
+# Convert ['foo\nbar'] to ['foo', 'bar']
4590
+def expandLineBreaks(mylist):
4591
+   ret = []
4592
+   for line in mylist:
4593
+       ret.extend(line.split('\n'))
4594
+   return ret
4595
+
4596
+def compile_filters(filters, errmsg='Filter'):
4597
+   if filters:
4598
+       for i in range(len(filters)):
4599
+           patt,repl = filters[i]
4600
+           try: rgx = re.compile(patt)
4601
+           except: Error("%s: '%s'"%(errmsg, patt))
4602
+           filters[i] = (rgx,repl)
4603
+   return filters
4604
+
4605
+def enclose_me(tagname, txt):
4606
+   return TAGS.get(tagname+'Open') + txt + TAGS.get(tagname+'Close')
4607
+
4608
+def beautify_me(name, line):
4609
+   "where name is: bold, italic, underline or strike"
4610
+
4611
+   # Exception: Doesn't parse an horizontal bar as strike
4612
+   if name == 'strike' and regex['bar'].search(line): return line
4613
+   
4614
+   name  = 'font%s' % name.capitalize()
4615
+   open_ = TAGS['%sOpen'%name]
4616
+   close = TAGS['%sClose'%name]
4617
+   txt = r'%s\1%s'%(open_, close)
4618
+   line = regex[name].sub(txt,line)
4619
+   return line
4620
+
4621
+def get_tagged_link(label, url):
4622
+   ret = ''
4623
+   target = CONF['target']
4624
+   image_re = regex['img']
4625
+   
4626
+   # Set link type
4627
+   if regex['email'].match(url):
4628
+       linktype = 'email'
4629
+   else:
4630
+       linktype = 'url';
4631
+   
4632
+   # Escape specials from TEXT parts
4633
+   label = doEscape(target,label)
4634
+   
4635
+   # Escape specials from link URL
4636
+   if not rules['linkable'] or rules['escapeurl']:
4637
+       url = doEscape(target, url)
4638
+   
4639
+   # Adding protocol to guessed link
4640
+   guessurl = ''
4641
+   if linktype == 'url' and \
4642
+      re.match('(?i)'+regex['_urlskel']['guess'], url):
4643
+       if url[0] in 'Ww': guessurl = 'http://' +url
4644
+       else             : guessurl =  'ftp://' +url
4645
+       
4646
+       # Not link aware targets -> protocol is useless
4647
+       if not rules['linkable']: guessurl = ''
4648
+   
4649
+   # Simple link (not guessed)
4650
+   if not label and not guessurl:
4651
+       if CONF['mask-email'] and linktype == 'email':
4652
+           # Do the email mask feature (no TAGs, just text)
4653
+           url = url.replace('@', ' (a) ')
4654
+           url = url.replace('.', ' ')
4655
+           url = "<%s>" % url
4656
+           if rules['linkable']: url = doEscape(target, url)
4657
+           ret = url
4658
+       else:
4659
+           # Just add link data to tag
4660
+           tag = TAGS[linktype]
4661
+           ret = regex['x'].sub(url,tag)
4662
+   
4663
+   # Named link or guessed simple link
4664
+   else:
4665
+       # Adjusts for guessed link
4666
+       if not label: label = url         # no   protocol
4667
+       if guessurl : url   = guessurl    # with protocol
4668
+       
4669
+       # Image inside link!
4670
+       if image_re.match(label):
4671
+           if rules['imglinkable']:  # get image tag
4672
+               label = parse_images(label)
4673
+           else:                     #  img@link !supported
4674
+               label = "(%s)"%image_re.match(label).group(1)
4675
+       
4676
+       # Putting data on the right appearance order
4677
+       if rules['labelbeforelink'] or not rules['linkable']:
4678
+           urlorder = [label, url]   # label before link
4679
+       else:
4680
+           urlorder = [url, label]   # link before label
4681
+       
4682
+       # Add link data to tag (replace \a's)
4683
+       ret = TAGS["%sMark"%linktype]
4684
+       for data in urlorder:
4685
+           ret = regex['x'].sub(data,ret,1)
4686
+   
4687
+   return ret
4688
+
4689
+
4690
+def parse_deflist_term(line):
4691
+   "Extract and parse definition list term contents"
4692
+   img_re = regex['img']
4693
+   term   = regex['deflist'].search(line).group(3)
4694
+   
4695
+   # Mask image inside term as (image.jpg), where not supported
4696
+   if not rules['imgasdefterm'] and img_re.search(term):
4697
+       while img_re.search(term):
4698
+           imgfile = img_re.search(term).group(1)
4699
+           term = img_re.sub('(%s)'%imgfile, term, 1)
4700
+   
4701
+   #TODO tex: escape ] on term. \], \rbrack{} and \verb!]! don't work :(
4702
+   return term
4703
+
4704
+
4705
+def get_image_align(line):
4706
+   "Return the image (first found) align for the given line"
4707
+   
4708
+   # First clear marks that can mess align detection
4709
+   line = re.sub(SEPARATOR+'$', '', line)  # remove deflist sep
4710
+   line = re.sub('^'+SEPARATOR, '', line)  # remove list sep
4711
+   line = re.sub('^[\t]+'     , '', line)  # remove quote mark
4712
+   
4713
+   # Get image position on the line
4714
+   m = regex['img'].search(line)
4715
+   ini = m.start() ; head = 0
4716
+   end = m.end()   ; tail = len(line)
4717
+   
4718
+   # The align detection algorithm
4719
+   if   ini == head and end != tail: align = 'left'   # ^img + text$
4720
+   elif ini != head and end == tail: align = 'right'  # ^text + img$
4721
+   else                            : align = 'center' # default align
4722
+   
4723
+   # Some special cases
4724
+   if BLOCK.isblock('table'): align = 'center'    # ignore when table
4725
+#  if TARGET == 'mgp' and align == 'center': align = 'center'
4726
+   
4727
+   return align
4728
+
4729
+
4730
+# Reference: http://www.iana.org/assignments/character-sets
4731
+# http://www.drclue.net/F1.cgi/HTML/META/META.html
4732
+def get_encoding_string(enc, target):
4733
+   if not enc: return ''
4734
+   # Target specific translation table
4735
+   translate = {
4736
+       'tex': {
4737
+           # missing: ansinew , applemac , cp437 , cp437de , cp865
4738
+           'utf-8'       : 'utf8',
4739
+           'us-ascii'    : 'ascii',
4740
+           'windows-1250': 'cp1250',
4741
+           'windows-1252': 'cp1252',
4742
+           'ibm850'      : 'cp850',
4743
+           'ibm852'      : 'cp852',
4744
+           'iso-8859-1'  : 'latin1',
4745
+           'iso-8859-2'  : 'latin2',
4746
+           'iso-8859-3'  : 'latin3',
4747
+           'iso-8859-4'  : 'latin4',
4748
+           'iso-8859-5'  : 'latin5',
4749
+           'iso-8859-9'  : 'latin9',
4750
+           'koi8-r'      : 'koi8-r'
4751
+       }
4752
+   }
4753
+   # Normalization
4754
+   enc = re.sub('(?i)(us[-_]?)?ascii|us|ibm367','us-ascii'  , enc)
4755
+   enc = re.sub('(?i)(ibm|cp)?85([02])'        ,'ibm85\\2'  , enc)
4756
+   enc = re.sub('(?i)(iso[_-]?)?8859[_-]?'     ,'iso-8859-' , enc)
4757
+   enc = re.sub('iso-8859-($|[^1-9]).*'        ,'iso-8859-1', enc)
4758
+   # Apply translation table
4759
+   try: enc = translate[target][enc.lower()]
4760
+   except: pass
4761
+   return enc
4762
+
4763
+
4764
+##############################################################################
4765
+##MerryChristmas,IdontwanttofighttonightwithyouImissyourbodyandIneedyourlove##
4766
+##############################################################################
4767
+
4768
+
4769
+def process_source_file(file_='', noconf=0, contents=[]):
4770
+   """
4771
+   Find and Join all the configuration available for a source file.
4772
+   No sanity checking is done on this step.
4773
+   It also extracts the source document parts into separate holders.
4774
+   
4775
+   The config scan order is:
4776
+       1. The user configuration file (i.e. $HOME/.txt2tagsrc)
4777
+       2. The source document's CONF area
4778
+       3. The command line options
4779
+
4780
+   The return data is a tuple of two items:
4781
+       1. The parsed config dictionary
4782
+       2. The document's parts, as a (head, conf, body) tuple
4783
+   
4784
+   All the conversion process will be based on the data and
4785
+   configuration returned by this function.
4786
+   The source files is read on this step only.
4787
+   """
4788
+   if contents:
4789
+       source = SourceDocument(contents=contents)
4790
+   else:
4791
+       source = SourceDocument(file_)
4792
+   head, conf, body = source.split()
4793
+   Message(_("Source document contents stored"),2)
4794
+   if not noconf:
4795
+       # Read document config
4796
+       source_raw = source.get_raw_config()
4797
+       # Join all the config directives found, then parse it
4798
+       full_raw = RC_RAW + source_raw + CMDLINE_RAW
4799
+       Message(_("Parsing and saving all config found (%03d items)") % (len(full_raw)), 1)
4800
+       full_parsed = ConfigMaster(full_raw).parse()
4801
+       # Add manually the filename to the conf dic
4802
+       if contents:
4803
+           full_parsed['sourcefile'] = MODULEIN
4804
+           full_parsed['infile'] = MODULEIN
4805
+           full_parsed['outfile'] = MODULEOUT
4806
+       else:
4807
+           full_parsed['sourcefile'] = file_
4808
+       # Maybe should we dump the config found?
4809
+       if full_parsed.get('dump-config'):
4810
+           dumpConfig(source_raw, full_parsed)
4811
+           Quit()
4812
+       # The user just want to know a single config value (hidden feature)
4813
+       #TODO pick a better name than --show-config-value
4814
+       elif full_parsed.get('show-config-value'):
4815
+           config_value = full_parsed.get(full_parsed['show-config-value'])
4816
+           if config_value:
4817
+               if isinstance(config_value, type([])):
4818
+                   print('\n'.join(config_value))
4819
+               else:
4820
+                   print(config_value)
4821
+           Quit()
4822
+       # Okay, all done
4823
+       Debug("FULL config for this file: %s"%full_parsed, 1)
4824
+   else:
4825
+       full_parsed = {}
4826
+   return full_parsed, (head,conf,body)
4827
+
4828
+def get_infiles_config(infiles):
4829
+   """
4830
+   Find and Join into a single list, all configuration available
4831
+   for each input file. This function is supposed to be the very
4832
+   first one to be called, before any processing.
4833
+   """
4834
+   return list(map(process_source_file, infiles))
4835
+
4836
+def convert_this_files(configs):
4837
+   global CONF
4838
+   for myconf,doc in configs:                 # multifile support
4839
+       target_head = []
4840
+       target_toc  = []
4841
+       target_body = []
4842
+       target_foot = []
4843
+       source_head, source_conf, source_body = doc
4844
+       myconf = ConfigMaster().sanity(myconf)
4845
+       # Compose the target file Headers
4846
+       #TODO escape line before?
4847
+       #TODO see exceptions by tex and mgp
4848
+       Message(_("Composing target Headers"),1)
4849
+       target_head = doHeader(source_head, myconf)
4850
+       # Parse the full marked body into tagged target
4851
+       first_body_line = (len(source_head) or 1)+ len(source_conf) + 1
4852
+       Message(_("Composing target Body"),1)
4853
+       target_body, marked_toc = convert(source_body, myconf, firstlinenr=first_body_line)
4854
+       # If dump-source, we're done
4855
+       if myconf['dump-source']:
4856
+           for line in source_head+source_conf+target_body:
4857
+               print(line)
4858
+           return
4859
+
4860
+       # Close the last slide
4861
+       if myconf['slides'] and not myconf['toc-only'] and myconf['target'] == 'art':
4862
+           n = (myconf['height'] - 1) - (AA_COUNT % (myconf['height'] - 1) + 1)
4863
+           target_body = target_body + ([''] * n) + [aa_line(AA['bar2'], myconf['width'])]
4864
+
4865
+       # Compose the target file Footer
4866
+       Message(_("Composing target Footer"),1)
4867
+       target_foot = doFooter(myconf)
4868
+
4869
+       # Make TOC (if needed)
4870
+       Message(_("Composing target TOC"),1)
4871
+       tagged_toc  = toc_tagger(marked_toc, myconf)
4872
+       target_toc  = toc_formatter(tagged_toc, myconf)
4873
+       target_body = toc_inside_body(target_body, target_toc, myconf)
4874
+       if not AUTOTOC and not myconf['toc-only']: target_toc = []
4875
+       # Finally, we have our document
4876
+       outlist = target_head + target_toc + target_body + target_foot
4877
+       # If on GUI, abort before finish_him
4878
+       # If module, return finish_him as list
4879
+       # Else, write results to file or STDOUT
4880
+       if GUI:
4881
+           return outlist, myconf
4882
+       elif myconf.get('outfile') == MODULEOUT:
4883
+           return finish_him(outlist, myconf), myconf
4884
+       else:
4885
+           Message(_("Saving results to the output file"),1)
4886
+           finish_him(outlist, myconf)
4887
+
4888
+
4889
+def parse_images(line):
4890
+   "Tag all images found"
4891
+   while regex['img'].search(line) and TAGS['img'] != '[\a]':
4892
+       txt = regex['img'].search(line).group(1)
4893
+       tag = TAGS['img']
4894
+       
4895
+       # If target supports image alignment, here we go
4896
+       if rules['imgalignable']:
4897
+           
4898
+           align = get_image_align(line)         # right
4899
+           align_name = align.capitalize()       # Right
4900
+           
4901
+           # The align is a full tag, or part of the image tag (~A~)
4902
+           if TAGS['imgAlign'+align_name]:
4903
+               tag = TAGS['imgAlign'+align_name]
4904
+           else:
4905
+               align_tag = TAGS['_imgAlign'+align_name]
4906
+               tag = regex['_imgAlign'].sub(align_tag, tag, 1)
4907
+               
4908
+           # Dirty fix to allow centered solo images
4909
+           if align == 'center' and TARGET in ('html','xhtml'):
4910
+               rest = regex['img'].sub('',line,1)
4911
+               if re.match('^\s+$', rest):
4912
+                   tag = "<center>%s</center>" %tag
4913
+       
4914
+       if TARGET == 'tex':
4915
+           tag = re.sub(r'\\b',r'\\\\b',tag)
4916
+           txt = txt.replace('_', 'vvvvTexUndervvvv')
4917
+       
4918
+       # Ugly hack to avoid infinite loop when target's image tag contains []
4919
+       tag = tag.replace('[', 'vvvvEscapeSquareBracketvvvv')
4920
+       
4921
+       line = regex['img'].sub(tag,line,1)
4922
+       line = regex['x'].sub(txt,line,1)
4923
+   return line.replace('vvvvEscapeSquareBracketvvvv','[')
4924
+
4925
+
4926
+def add_inline_tags(line):
4927
+   # Beautifiers
4928
+   for beauti in ('bold', 'italic', 'underline', 'strike'):
4929
+       if regex['font%s'%beauti.capitalize()].search(line):
4930
+           line = beautify_me(beauti, line)
4931
+   
4932
+   line = parse_images(line)
4933
+   return line
4934
+
4935
+
4936
+def get_include_contents(file_, path=''):
4937
+   "Parses %!include: value and extract file contents"
4938
+   ids = {'`':'verb', '"':'raw', "'":'tagged' }
4939
+   id_ = 't2t'
4940
+   # Set include type and remove identifier marks
4941
+   mark = file_[0]
4942
+   if mark in ids.keys():
4943
+       if file_[:2] == file_[-2:] == mark*2:
4944
+           id_ = ids[mark]      # set type
4945
+           file_ = file_[2:-2]  # remove marks
4946
+   # Handle remote dir execution
4947
+   filepath = os.path.join(path, file_)
4948
+   # Read included file contents
4949
+   lines = Readfile(filepath, remove_linebreaks=1)
4950
+   # Default txt2tags marked text, just BODY matters
4951
+   if id_ == 't2t':
4952
+       lines = get_file_body(filepath)
4953
+       #TODO fix images relative path if file has a path, ie.: chapter1/index.t2t (wait until tree parsing)
4954
+       #TODO for the images path fix, also respect outfile path, if different from infile (wait until tree parsing)
4955
+       lines.insert(0, '%%INCLUDED(%s) starts here: %s'%(id_,file_))
4956
+       # This appears when included hit EOF with verbatim area open
4957
+       #lines.append('%%INCLUDED(%s) ends here: %s'%(id_,file_))
4958
+   return id_, lines
4959
+
4960
+
4961
+def set_global_config(config):
4962
+   global CONF, TAGS, regex, rules, TARGET
4963
+   CONF   = config
4964
+   rules  = getRules(CONF)
4965
+   TAGS   = getTags(CONF)
4966
+   regex  = getRegexes()
4967
+   TARGET = config['target']  # save for buggy functions that need global
4968
+
4969
+
4970
+def convert(bodylines, config, firstlinenr=1):
4971
+   global BLOCK, TITLE
4972
+   
4973
+   set_global_config(config)
4974
+   
4975
+   target = config['target']
4976
+   BLOCK = BlockMaster()
4977
+   MASK  =  MaskMaster()
4978
+   TITLE = TitleMaster()
4979
+   
4980
+   ret = []
4981
+   dump_source = []
4982
+   f_lastwasblank = 0
4983
+   
4984
+   # Compiling all PreProc regexes
4985
+   pre_filter = compile_filters(
4986
+       CONF['preproc'], _('Invalid PreProc filter regex'))
4987
+   
4988
+   # Let's mark it up!
4989
+   linenr = firstlinenr-1
4990
+   lineref = 0
4991
+   while lineref < len(bodylines):
4992
+       # Defaults
4993
+       MASK.reset()
4994
+       results_box = ''
4995
+       
4996
+       untouchedline = bodylines[lineref]
4997
+       dump_source.append(untouchedline)
4998
+       
4999
+       line = re.sub('[\n\r]+$','',untouchedline)   # del line break
5000
+       
5001
+       # Apply PreProc filters
5002
+       if pre_filter:
5003
+           errmsg = _('Invalid PreProc filter replacement')
5004
+           for rgx,repl in pre_filter:
5005
+               try: line = rgx.sub(repl, line)
5006
+               except: Error("%s: '%s'"%(errmsg, repl))
5007
+       
5008
+       line = maskEscapeChar(line)                  # protect \ char
5009
+       linenr  += 1
5010
+       lineref += 1
5011
+       
5012
+       Debug(repr(line), 2, linenr)  # heavy debug: show each line
5013
+       
5014
+       #------------------[ Comment Block ]------------------------
5015
+       
5016
+       # We're already on a comment block
5017
+       if BLOCK.block() == 'comment':
5018
+       
5019
+           # Closing comment
5020
+           if regex['blockCommentClose'].search(line):
5021
+               ret.extend(BLOCK.blockout() or [])
5022
+               continue
5023
+           
5024
+           # Normal comment-inside line. Ignore it.
5025
+           continue
5026
+       
5027
+       # Detecting comment block init
5028
+       if regex['blockCommentOpen'].search(line) \
5029
+          and BLOCK.block() not in BLOCK.exclusive:
5030
+           ret.extend(BLOCK.blockin('comment'))
5031
+           continue
5032
+
5033
+       #-------------------------[ Tagged Text ]----------------------
5034
+
5035
+       # We're already on a tagged block
5036
+       if BLOCK.block() == 'tagged':
5037
+       
5038
+           # Closing tagged
5039
+           if regex['blockTaggedClose'].search(line):
5040
+               ret.extend(BLOCK.blockout())
5041
+               continue
5042
+           
5043
+           # Normal tagged-inside line
5044
+           BLOCK.holdadd(line)
5045
+           continue
5046
+       
5047
+       # Detecting tagged block init
5048
+       if regex['blockTaggedOpen'].search(line) \
5049
+          and BLOCK.block() not in BLOCK.exclusive:
5050
+           ret.extend(BLOCK.blockin('tagged'))
5051
+           continue
5052
+       
5053
+       # One line tagged text
5054
+       if regex['1lineTagged'].search(line) \
5055
+          and BLOCK.block() not in BLOCK.exclusive:
5056
+           ret.extend(BLOCK.blockin('tagged'))
5057
+           line = regex['1lineTagged'].sub('',line)
5058
+           BLOCK.holdadd(line)
5059
+           ret.extend(BLOCK.blockout())
5060
+           continue
5061
+       
5062
+       #-------------------------[ Raw Text ]----------------------
5063
+       
5064
+       # We're already on a raw block
5065
+       if BLOCK.block() == 'raw':
5066
+       
5067
+           # Closing raw
5068
+           if regex['blockRawClose'].search(line):
5069
+               ret.extend(BLOCK.blockout())
5070
+               continue
5071
+           
5072
+           # Normal raw-inside line
5073
+           BLOCK.holdadd(line)
5074
+           continue
5075
+       
5076
+       # Detecting raw block init
5077
+       if regex['blockRawOpen'].search(line) \
5078
+          and BLOCK.block() not in BLOCK.exclusive:
5079
+           ret.extend(BLOCK.blockin('raw'))
5080
+           continue
5081
+       
5082
+       # One line raw text
5083
+       if regex['1lineRaw'].search(line) \
5084
+          and BLOCK.block() not in BLOCK.exclusive:
5085
+           ret.extend(BLOCK.blockin('raw'))
5086
+           line = regex['1lineRaw'].sub('',line)
5087
+           BLOCK.holdadd(line)
5088
+           ret.extend(BLOCK.blockout())
5089
+           continue
5090
+       
5091
+       #------------------------[ Verbatim  ]----------------------
5092
+       
5093
+       #TIP We'll never support beautifiers inside verbatim
5094
+       
5095
+       # Closing table mapped to verb
5096
+       if BLOCK.block() == 'verb' \
5097
+          and BLOCK.prop('mapped') == 'table' \
5098
+          and not regex['table'].search(line):
5099
+           ret.extend(BLOCK.blockout())
5100
+       
5101
+       # We're already on a verb block
5102
+       if BLOCK.block() == 'verb':
5103
+           
5104
+           # Closing verb
5105
+           if regex['blockVerbClose'].search(line):
5106
+               ret.extend(BLOCK.blockout())
5107
+               continue
5108
+           
5109
+           # Normal verb-inside line
5110
+           BLOCK.holdadd(line)
5111
+           continue
5112
+       
5113
+       # Detecting verb block init
5114
+       if regex['blockVerbOpen'].search(line) \
5115
+          and BLOCK.block() not in BLOCK.exclusive:
5116
+           ret.extend(BLOCK.blockin('verb'))
5117
+           f_lastwasblank = 0
5118
+           continue
5119
+       
5120
+       # One line verb-formatted text
5121
+       if regex['1lineVerb'].search(line) \
5122
+          and BLOCK.block() not in BLOCK.exclusive:
5123
+           ret.extend(BLOCK.blockin('verb'))
5124
+           line = regex['1lineVerb'].sub('',line)
5125
+           BLOCK.holdadd(line)
5126
+           ret.extend(BLOCK.blockout())
5127
+           f_lastwasblank = 0
5128
+           continue
5129
+       
5130
+       # Tables are mapped to verb when target is not table-aware
5131
+       if not rules['tableable'] and regex['table'].search(line):
5132
+           if not BLOCK.isblock('verb'):
5133
+               ret.extend(BLOCK.blockin('verb'))
5134
+               BLOCK.propset('mapped', 'table')
5135
+               BLOCK.holdadd(line)
5136
+               continue
5137
+       
5138
+       #---------------------[ blank lines ]-----------------------
5139
+       
5140
+       if regex['blankline'].search(line):
5141
+           
5142
+           # Close open paragraph
5143
+           if BLOCK.isblock('para'):
5144
+               ret.extend(BLOCK.blockout())
5145
+               f_lastwasblank = 1
5146
+               continue
5147
+           
5148
+           # Close all open tables
5149
+           if BLOCK.isblock('table'):
5150
+               ret.extend(BLOCK.blockout())
5151
+               f_lastwasblank = 1
5152
+               continue
5153
+           
5154
+           # Close all open quotes
5155
+           while BLOCK.isblock('quote'):
5156
+               ret.extend(BLOCK.blockout())
5157
+           
5158
+           # Closing all open lists
5159
+           if f_lastwasblank:          # 2nd consecutive blank
5160
+               if BLOCK.block().endswith('list'):
5161
+                   BLOCK.holdaddsub('')   # helps parser
5162
+               while BLOCK.depth:  # closes list (if any)
5163
+                   ret.extend(BLOCK.blockout())
5164
+               continue            # ignore consecutive blanks
5165
+           
5166
+           # Paragraph (if any) is wanted inside lists also
5167
+           if BLOCK.block().endswith('list'):
5168
+               BLOCK.holdaddsub('')
5169
+           
5170
+           f_lastwasblank = 1
5171
+           continue
5172
+       
5173
+       
5174
+       #---------------------[ special ]---------------------------
5175
+       
5176
+       if regex['special'].search(line):
5177
+           
5178
+           targ, key, val = ConfigLines().parse_line(line, None, target)
5179
+           
5180
+           if key:
5181
+               Debug("Found config '%s', value '%s'" % (key, val), 1, linenr)
5182
+           else:
5183
+               Debug('Bogus Special Line', 1, linenr)
5184
+               
5185
+           # %!include command
5186
+           if key == 'include':
5187
+                       
5188
+               incpath = os.path.dirname(CONF['sourcefile'])
5189
+               incfile = val
5190
+               err = _('A file cannot include itself (loop!)')
5191
+               if CONF['sourcefile'] == incfile:
5192
+                   Error("%s: %s"%(err,incfile))
5193
+               inctype, inclines = get_include_contents(incfile, incpath)
5194
+               
5195
+               # Verb, raw and tagged are easy
5196
+               if inctype != 't2t':
5197
+                   ret.extend(BLOCK.blockin(inctype))
5198
+                   BLOCK.holdextend(inclines)
5199
+                   ret.extend(BLOCK.blockout())
5200
+               else:
5201
+                   # Insert include lines into body
5202
+                   #TODO include maxdepth limit
5203
+                   bodylines = bodylines[:lineref] + inclines + bodylines[lineref:]
5204
+                   #TODO fix path if include@include
5205
+                   # Remove %!include call
5206
+                   if CONF['dump-source']:
5207
+                       dump_source.pop()
5208
+               
5209
+               # This line is done, go to next
5210
+               continue
5211
+               
5212
+           # %!csv command
5213
+           elif key == 'csv':
5214
+
5215
+               if not csv:
5216
+                   Error("Python module 'csv' not found, but needed for %!csv")
5217
+
5218
+               table = []
5219
+               filename = val
5220
+               reader = csv.reader(Readfile(filename))
5221
+               
5222
+               # Convert each CSV line to a txt2tags' table line
5223
+               # foo,bar,baz -> | foo | bar | baz |
5224
+               try:
5225
+                   for row in reader:
5226
+                       table.append('| %s |' % ' | '.join(row))
5227
+               except csv.Error as e:
5228
+                   Error('CSV: file %s: %s' % (filename, e))
5229
+
5230
+               # Parse and convert the new table
5231
+               # Note: cell contents is raw, no t2t marks are parsed
5232
+               if rules['tableable']:
5233
+                   ret.extend(BLOCK.blockin('table'))
5234
+                   if table:
5235
+                       BLOCK.tableparser.__init__(table[0])
5236
+                       for row in table:
5237
+                           tablerow = TableMaster().parse_row(row)
5238
+                           BLOCK.tableparser.add_row(tablerow)
5239
+                           
5240
+                           # Very ugly, but necessary for escapes
5241
+                           line = SEPARATOR.join(tablerow['cells'])
5242
+                           BLOCK.holdadd(doEscape(target, line))
5243
+                       ret.extend(BLOCK.blockout())
5244
+
5245
+               # Tables are mapped to verb when target is not table-aware
5246
+               else:
5247
+                   if target == 'art' and table:
5248
+                       table = aa_table(table)
5249
+                   ret.extend(BLOCK.blockin('verb'))
5250
+                   BLOCK.propset('mapped', 'table')
5251
+                   for row in table:
5252
+                       BLOCK.holdadd(row)
5253
+                   ret.extend(BLOCK.blockout())
5254
+                   
5255
+               # This line is done, go to next
5256
+               continue
5257
+                   
5258
+       #---------------------[ dump-source ]-----------------------
5259
+       
5260
+       # We don't need to go any further
5261
+       if CONF['dump-source']:
5262
+           continue
5263
+       
5264
+       #---------------------[ Comments ]--------------------------
5265
+       
5266
+       # Just skip them (if not macro)
5267
+       if regex['comment'].search(line) and not \
5268
+          regex['macros'].match(line) and not \
5269
+          regex['toc'].match(line):
5270
+           continue
5271
+       
5272
+       #---------------------[ Triggers ]--------------------------
5273
+       
5274
+       # Valid line, reset blank status
5275
+       f_lastwasblank = 0
5276
+       
5277
+       # Any NOT quote line closes all open quotes
5278
+       if BLOCK.isblock('quote') and not regex['quote'].search(line):
5279
+           while BLOCK.isblock('quote'):
5280
+               ret.extend(BLOCK.blockout())
5281
+       
5282
+       # Any NOT table line closes an open table
5283
+       if BLOCK.isblock('table') and not regex['table'].search(line):
5284
+           ret.extend(BLOCK.blockout())
5285
+       
5286
+       
5287
+       #---------------------[ Horizontal Bar ]--------------------
5288
+
5289
+       if regex['bar'].search(line):
5290
+
5291
+           # Bars inside quotes are handled on the Quote processing
5292
+           # Otherwise we parse the bars right here
5293
+           #
5294
+           if not (BLOCK.isblock('quote') or regex['quote'].search(line)) \
5295
+               or (BLOCK.isblock('quote') and not rules['barinsidequote']):
5296
+
5297
+               # Close all the opened blocks
5298
+               ret.extend(BLOCK.blockin('bar'))
5299
+
5300
+               # Extract the bar chars (- or =)
5301
+               m = regex['bar'].search(line)
5302
+               bar_chars = m.group(2)
5303
+
5304
+               # Process and dump the tagged bar
5305
+               BLOCK.holdadd(bar_chars)
5306
+               ret.extend(BLOCK.blockout())
5307
+               Debug("BAR: %s"%line, 6)
5308
+
5309
+               # We're done, nothing more to process
5310
+               continue
5311
+
5312
+
5313
+       #---------------------[ Title ]-----------------------------
5314
+       
5315
+       if (regex['title'].search(line) or regex['numtitle'].search(line)) \
5316
+           and not BLOCK.block().endswith('list'):
5317
+
5318
+           if regex['title'].search(line):
5319
+               name = 'title'
5320
+           else:
5321
+               name = 'numtitle'
5322
+           
5323
+           # Close all the opened blocks
5324
+           ret.extend(BLOCK.blockin(name))
5325
+           
5326
+           # Process title
5327
+           TITLE.add(line)
5328
+           ret.extend(BLOCK.blockout())
5329
+           
5330
+           # We're done, nothing more to process
5331
+           continue
5332
+       
5333
+       #---------------------[ %%toc ]-----------------------
5334
+       
5335
+       # %%toc line closes paragraph
5336
+       if BLOCK.block() == 'para' and regex['toc'].search(line):
5337
+           ret.extend(BLOCK.blockout())
5338
+       
5339
+       #---------------------[ apply masks ]-----------------------
5340
+       
5341
+       line = MASK.mask(line)
5342
+       
5343
+       #XXX from here, only block-inside lines will pass
5344
+       
5345
+       #---------------------[ Quote ]-----------------------------
5346
+       
5347
+       if regex['quote'].search(line):
5348
+           
5349
+           # Store number of leading TABS
5350
+           quotedepth = len(regex['quote'].search(line).group(0))
5351
+           
5352
+           # SGML doesn't support nested quotes
5353
+           if rules['quotenotnested']: quotedepth = 1
5354
+           
5355
+           # Don't cross depth limit
5356
+           maxdepth = rules['quotemaxdepth']
5357
+           if maxdepth and quotedepth > maxdepth:
5358
+               quotedepth = maxdepth
5359
+           
5360
+           # New quote
5361
+           if not BLOCK.isblock('quote'):
5362
+               ret.extend(BLOCK.blockin('quote'))
5363
+           
5364
+           # New subquotes
5365
+           while BLOCK.depth < quotedepth:
5366
+               BLOCK.blockin('quote')
5367
+           
5368
+           # Closing quotes
5369
+           while quotedepth < BLOCK.depth:
5370
+               ret.extend(BLOCK.blockout())
5371
+           
5372
+           # Bar inside quote
5373
+           if regex['bar'].search(line) and rules['barinsidequote']:
5374
+               tempBlock = BlockMaster()
5375
+               tagged_bar = []
5376
+               tagged_bar.extend(tempBlock.blockin('bar'))
5377
+               tempBlock.holdadd(line)
5378
+               tagged_bar.extend(tempBlock.blockout())
5379
+               BLOCK.holdextend(tagged_bar)
5380
+               continue
5381
+
5382
+       #---------------------[ Lists ]-----------------------------
5383
+       
5384
+       # An empty item also closes the current list
5385
+       if BLOCK.block().endswith('list'):
5386
+           m = regex['listclose'].match(line)
5387
+           if m:
5388
+               listindent = m.group(1)
5389
+               listtype = m.group(2)
5390
+               currlisttype = BLOCK.prop('type')
5391
+               currlistindent = BLOCK.prop('indent')
5392
+               if listindent == currlistindent and \
5393
+                  listtype == currlisttype:
5394
+                   ret.extend(BLOCK.blockout())
5395
+                   continue
5396
+       
5397
+       if   regex['list'].search(line) or \
5398
+         regex['numlist'].search(line) or \
5399
+         regex['deflist'].search(line):
5400
+           
5401
+           listindent = BLOCK.prop('indent')
5402
+           listids = ''.join(LISTNAMES.keys())
5403
+           m = re.match('^( *)([%s]) '%listids, line)
5404
+           listitemindent = m.group(1)
5405
+           listtype = m.group(2)
5406
+           listname = LISTNAMES[listtype]
5407
+           results_box = BLOCK.holdadd
5408
+           
5409
+           # Del list ID (and separate term from definition)
5410
+           if listname == 'deflist':
5411
+               term = parse_deflist_term(line)
5412
+               line = regex['deflist'].sub(
5413
+                   SEPARATOR+term+SEPARATOR,line)
5414
+           else:
5415
+               line = regex[listname].sub(SEPARATOR,line)
5416
+           
5417
+           # Don't cross depth limit
5418
+           maxdepth = rules['listmaxdepth']
5419
+           if maxdepth and BLOCK.depth == maxdepth:
5420
+               if len(listitemindent) > len(listindent):
5421
+                   listitemindent = listindent
5422
+           
5423
+           # List bumping (same indent, diff mark)
5424
+           # Close the currently open list to clear the mess
5425
+           if BLOCK.block().endswith('list') \
5426
+              and listname != BLOCK.block() \
5427
+              and len(listitemindent) == len(listindent):
5428
+               ret.extend(BLOCK.blockout())
5429
+               listindent = BLOCK.prop('indent')
5430
+           
5431
+           # Open mother list or sublist
5432
+           if not BLOCK.block().endswith('list') or \
5433
+              len(listitemindent) > len(listindent):
5434
+               ret.extend(BLOCK.blockin(listname))
5435
+               BLOCK.propset('indent',listitemindent)
5436
+               BLOCK.propset('type',listtype)
5437
+           
5438
+           # Closing sublists
5439
+           while len(listitemindent) < len(BLOCK.prop('indent')):
5440
+               ret.extend(BLOCK.blockout())
5441
+           
5442
+           # O-oh, sublist before list ("\n\n  - foo\n- foo")
5443
+           # Fix: close sublist (as mother), open another list
5444
+           if not BLOCK.block().endswith('list'):
5445
+               ret.extend(BLOCK.blockin(listname))
5446
+               BLOCK.propset('indent',listitemindent)
5447
+               BLOCK.propset('type',listtype)
5448
+       
5449
+       #---------------------[ Table ]-----------------------------
5450
+       
5451
+       #TODO escape undesired format inside table
5452
+       #TODO add pm6 target
5453
+       if regex['table'].search(line):
5454
+           
5455
+           if not BLOCK.isblock('table'):   # first table line!
5456
+               ret.extend(BLOCK.blockin('table'))
5457
+               BLOCK.tableparser.__init__(line)
5458
+           
5459
+           tablerow = TableMaster().parse_row(line)
5460
+           BLOCK.tableparser.add_row(tablerow)     # save config
5461
+           
5462
+           # Maintain line to unmask and inlines
5463
+           # XXX Bug: | **bo | ld** | turns **bo\x01ld** and gets converted :(
5464
+           # TODO isolate unmask+inlines parsing to use here
5465
+           line = SEPARATOR.join(tablerow['cells'])
5466
+       
5467
+       #---------------------[ Paragraph ]-------------------------
5468
+       
5469
+       if not BLOCK.block() and \
5470
+          not line.count(MASK.tocmask): # new para!
5471
+           ret.extend(BLOCK.blockin('para'))
5472
+       
5473
+       
5474
+       ############################################################
5475
+       ############################################################
5476
+       ############################################################
5477
+       
5478
+       
5479
+       #---------------------[ Final Parses ]----------------------
5480
+       
5481
+       # The target-specific special char escapes for body lines
5482
+       line = doEscape(target,line)
5483
+       
5484
+       line = add_inline_tags(line)
5485
+       line = MASK.undo(line)
5486
+       
5487
+       
5488
+       #---------------------[ Hold or Return? ]-------------------
5489
+       
5490
+       ### Now we must choose where to put the parsed line
5491
+       #
5492
+       if not results_box:
5493
+           # List item extra lines
5494
+           if BLOCK.block().endswith('list'):
5495
+               results_box = BLOCK.holdaddsub
5496
+           # Other blocks
5497
+           elif BLOCK.block():
5498
+               results_box = BLOCK.holdadd
5499
+           # No blocks
5500
+           else:
5501
+               line = doFinalEscape(target, line)
5502
+               results_box = ret.append
5503
+       
5504
+       results_box(line)
5505
+   
5506
+   # EOF: close any open para/verb/lists/table/quotes
5507
+   Debug('EOF',7)
5508
+   while BLOCK.block():
5509
+       ret.extend(BLOCK.blockout())
5510
+   
5511
+   # Maybe close some opened title area?
5512
+   if rules['titleblocks']:
5513
+       ret.extend(TITLE.close_all())
5514
+   
5515
+   # Maybe a major tag to enclose body? (like DIV for CSS)
5516
+   if TAGS['bodyOpen' ]: ret.insert(0, TAGS['bodyOpen'])
5517
+   if TAGS['bodyClose']: ret.append(TAGS['bodyClose'])
5518
+   
5519
+   if CONF['toc-only']: ret = []
5520
+   marked_toc = TITLE.dump_marked_toc(CONF['toc-level'])
5521
+   
5522
+   # If dump-source, all parsing is ignored
5523
+   if CONF['dump-source']: ret = dump_source[:]
5524
+   
5525
+   return ret, marked_toc
5526
+
5527
+
5528
+
5529
+##############################################################################
5530
+################################### GUI ######################################
5531
+##############################################################################
5532
+#
5533
+# Tk help: http://python.org/topics/tkinter/
5534
+#    Tuto: http://ibiblio.org/obp/py4fun/gui/tkPhone.html
5535
+#          /usr/lib/python*/lib-tk/Tkinter.py
5536
+#
5537
+# grid table : row=0, column=0, columnspan=2, rowspan=2
5538
+# grid align : sticky='n,s,e,w' (North, South, East, West)
5539
+# pack place : side='top,bottom,right,left'
5540
+# pack fill  : fill='x,y,both,none', expand=1
5541
+# pack align : anchor='n,s,e,w' (North, South, East, West)
5542
+# padding    : padx=10, pady=10, ipadx=10, ipady=10 (internal)
5543
+# checkbox   : offvalue is return if the _user_ deselected the box
5544
+# label align: justify=left,right,center
5545
+
5546
+def load_GUI_resources():
5547
+   "Load all extra modules and methods used by GUI"
5548
+   global askopenfilename, showinfo, showwarning, showerror, tkinter
5549
+   from tkinter.filedialog import askopenfilename
5550
+   from tkinter.messagebox import showinfo,showwarning,showerror
5551
+   import tkinter
5552
+
5553
+class Gui:
5554
+   "Graphical Tk Interface"
5555
+   def __init__(self, conf={}):
5556
+       self.root = tkinter.Tk()    # mother window, come to butthead
5557
+       self.root.title(my_name)    # window title bar text
5558
+       self.window = self.root     # variable "focus" for inclusion
5559
+       self.row = 0                # row count for grid()
5560
+       
5561
+       self.action_length = 150    # left column length (pixel)
5562
+       self.frame_margin  = 10     # frame margin size  (pixel)
5563
+       self.frame_border  = 6      # frame border size  (pixel)
5564
+       
5565
+       # The default Gui colors, can be changed by %!guicolors
5566
+       self.dft_gui_colors = ['#6c6','white','#cf9','#030']
5567
+       self.gui_colors = []
5568
+       self.bg1 = self.fg1 = self.bg2 = self.fg2 = ''
5569
+       
5570
+       # On Tk, vars need to be set/get using setvar()/get()
5571
+       self.infile  = self.setvar('')
5572
+       self.target  = self.setvar('')
5573
+       self.target_name = self.setvar('')
5574
+       
5575
+       # The checks appearance order
5576
+       self.checks = [
5577
+           'headers', 'enum-title', 'toc', 'mask-email', 'toc-only', 'stdout'
5578
+       ]
5579
+       
5580
+       # Creating variables for all checks
5581
+       for check in self.checks:
5582
+           setattr(self, 'f_'+check, self.setvar(''))
5583
+       
5584
+       # Load RC config
5585
+       self.conf = {}
5586
+       if conf: self.load_config(conf)
5587
+   
5588
+   def load_config(self, conf):
5589
+       self.conf = conf
5590
+       self.gui_colors = conf.get('guicolors') or self.dft_gui_colors
5591
+       self.bg1, self.fg1, self.bg2, self.fg2 = self.gui_colors
5592
+       self.root.config(bd=15,bg=self.bg1)
5593
+   
5594
+   ### Config as dic for python 1.5 compat (**opts don't work :( )
5595
+   def entry(self, **opts): return tkinter.Entry(self.window, opts)
5596
+   def label(self, txt='', bg=None, **opts):
5597
+       opts.update({'text':txt,'bg':bg or self.bg1})
5598
+       return tkinter.Label(self.window, opts)
5599
+   def button(self,name,cmd,**opts):
5600
+       opts.update({'text':name,'command':cmd})
5601
+       return tkinter.Button(self.window, opts)
5602
+   def check(self,name,checked=0,**opts):
5603
+       bg, fg = self.bg2, self.fg2
5604
+       opts.update({
5605
+           'text':name,
5606
+           'onvalue':1,
5607
+           'offvalue':0,
5608
+           'activeforeground':fg,
5609
+           'activebackground':bg,
5610
+           'highlightbackground':bg,
5611
+           'fg':fg,
5612
+           'bg':bg,
5613
+           'anchor':'w'
5614
+       })
5615
+       chk = tkinter.Checkbutton(self.window, opts)
5616
+       if checked: chk.select()
5617
+       chk.grid(columnspan=2, sticky='w', padx=0)
5618
+   def menu(self,sel,items):
5619
+       return tkinter.OptionMenu(*(self.window,sel)+tuple(items))
5620
+   
5621
+   # Handy auxiliary functions
5622
+   def action(self, txt):
5623
+       self.label(
5624
+           txt,
5625
+           fg=self.fg1,
5626
+           bg=self.bg1,
5627
+           wraplength=self.action_length).grid(column=0,row=self.row)
5628
+   def frame_open(self):
5629
+       self.window = tkinter.Frame(
5630
+           self.root,
5631
+           bg=self.bg2,
5632
+           borderwidth=self.frame_border)
5633
+   def frame_close(self):
5634
+       self.window.grid(
5635
+           column=1,
5636
+           row=self.row,
5637
+           sticky='w',
5638
+           padx=self.frame_margin)
5639
+       self.window = self.root
5640
+       self.label('').grid()
5641
+       self.row += 2   # update row count
5642
+   def target_name2key(self):
5643
+       name = self.target_name.get()
5644
+       target = [x for x in TARGETS if TARGET_NAMES[x] == name]
5645
+       try   : key = target[0]
5646
+       except: key = ''
5647
+       self.target = self.setvar(key)
5648
+   def target_key2name(self):
5649
+       key = self.target.get()
5650
+       name = TARGET_NAMES.get(key) or key
5651
+       self.target_name = self.setvar(name)
5652
+   
5653
+   def exit(self): self.root.destroy()
5654
+   def setvar(self, val): z = tkinter.StringVar() ; z.set(val) ; return z
5655
+   
5656
+   def askfile(self):
5657
+       ftypes= [(_('txt2tags files'), ('*.t2t','*.txt')), (_('All files'),'*')]
5658
+       newfile = askopenfilename(filetypes=ftypes)
5659
+       if newfile:
5660
+           self.infile.set(newfile)
5661
+           newconf = process_source_file(newfile)[0]
5662
+           newconf = ConfigMaster().sanity(newconf, gui=1)
5663
+           # Restate all checkboxes after file selection
5664
+           #TODO how to make a refresh without killing it?
5665
+           self.root.destroy()
5666
+           self.__init__(newconf)
5667
+           self.mainwindow()
5668
+   
5669
+   def scrollwindow(self, txt='no text!', title=''):
5670
+       # Create components
5671
+       win    = tkinter.Toplevel() ; win.title(title)
5672
+       frame  = tkinter.Frame(win)
5673
+       scroll = tkinter.Scrollbar(frame)
5674
+       text   = tkinter.Text(frame,yscrollcommand=scroll.set)
5675
+       button = tkinter.Button(win)
5676
+       # Config
5677
+       text.insert(tkinter.END, '\n'.join(txt))
5678
+       scroll.config(command=text.yview)
5679
+       button.config(text=_('Close'), command=win.destroy)
5680
+       button.focus_set()
5681
+       # Packing
5682
+       text.pack(side='left', fill='both', expand=1)
5683
+       scroll.pack(side='right', fill='y')
5684
+       frame.pack(fill='both', expand=1)
5685
+       button.pack(ipadx=30)
5686
+   
5687
+   def runprogram(self):
5688
+       global CMDLINE_RAW
5689
+       # Prepare
5690
+       self.target_name2key()
5691
+       infile, target = self.infile.get(), self.target.get()
5692
+       # Sanity
5693
+       if not target:
5694
+           showwarning(my_name,_("You must select a target type!"))
5695
+           return
5696
+       if not infile:
5697
+           showwarning(my_name,_("You must provide the source file location!"))
5698
+           return
5699
+       # Compose cmdline
5700
+       guiflags = []
5701
+       real_cmdline_conf = ConfigMaster(CMDLINE_RAW).parse()
5702
+       if 'infile' in real_cmdline_conf:
5703
+           del real_cmdline_conf['infile']
5704
+       if 'target' in real_cmdline_conf:
5705
+           del real_cmdline_conf['target']
5706
+       real_cmdline = CommandLine().compose_cmdline(real_cmdline_conf)
5707
+       default_outfile = ConfigMaster().get_outfile_name(
5708
+           {'sourcefile':infile, 'outfile':'', 'target':target})
5709
+       for opt in self.checks:
5710
+           val = int(getattr(self, 'f_%s'%opt).get() or "0")
5711
+           if opt == 'stdout': opt = 'outfile'
5712
+           on_config  = self.conf.get(opt) or 0
5713
+           on_cmdline = real_cmdline_conf.get(opt) or 0
5714
+           if opt == 'outfile':
5715
+               if on_config  == STDOUT: on_config = 1
5716
+               else: on_config = 0
5717
+               if on_cmdline == STDOUT: on_cmdline = 1
5718
+               else: on_cmdline = 0
5719
+           if val != on_config or (
5720
+             val == on_config == on_cmdline and
5721
+             opt in real_cmdline_conf):
5722
+               if val:
5723
+                   # Was not set, but user selected on GUI
5724
+                   Debug("user turned  ON: %s"%opt)
5725
+                   if opt == 'outfile': opt = '-o-'
5726
+                   else: opt = '--%s'%opt
5727
+               else:
5728
+                   # Was set, but user deselected on GUI
5729
+                   Debug("user turned OFF: %s"%opt)
5730
+                   if opt == 'outfile':
5731
+                       opt = "-o%s"%default_outfile
5732
+                   else: opt = '--no-%s'%opt
5733
+               guiflags.append(opt)
5734
+       cmdline = [my_name, '-t', target] + real_cmdline + guiflags + [infile]
5735
+       Debug('Gui/Tk cmdline: %s' % cmdline, 5)
5736
+       # Run!
5737
+       cmdline_raw_orig = CMDLINE_RAW
5738
+       try:
5739
+           # Fake the GUI cmdline as the real one, and parse file
5740
+           CMDLINE_RAW = CommandLine().get_raw_config(cmdline[1:])
5741
+           data = process_source_file(infile)
5742
+           # On GUI, convert_* returns the data, not finish_him()
5743
+           outlist, config = convert_this_files([data])
5744
+           # On GUI and STDOUT, finish_him() returns the data
5745
+           result = finish_him(outlist, config)
5746
+           # Show outlist in s a nice new window
5747
+           if result:
5748
+               outlist, config = result
5749
+               title = _('%s: %s converted to %s') % (
5750
+                   my_name,
5751
+                   os.path.basename(infile),
5752
+                   config['target'].upper())
5753
+               self.scrollwindow(outlist, title)
5754
+           # Show the "file saved" message
5755
+           else:
5756
+               msg = "%s\n\n  %s\n%s\n\n  %s\n%s"%(
5757
+                   _('Conversion done!'),
5758
+                   _('FROM:'), infile,
5759
+                   _('TO:'), config['outfile'])
5760
+               showinfo(my_name, msg)
5761
+       except error:         # common error (windowed), not quit
5762
+           pass
5763
+       except:               # fatal error (windowed and printed)
5764
+           errormsg = getUnknownErrorMessage()
5765
+           print(errormsg)
5766
+           showerror(_('%s FATAL ERROR!')%my_name,errormsg)
5767
+           self.exit()
5768
+       CMDLINE_RAW = cmdline_raw_orig
5769
+   
5770
+   def mainwindow(self):
5771
+       self.infile.set(self.conf.get('sourcefile') or '')
5772
+       self.target.set(self.conf.get('target') or _('-- select one --'))
5773
+       outfile = self.conf.get('outfile')
5774
+       if outfile == STDOUT:                  # map -o-
5775
+           self.conf['stdout'] = 1
5776
+       if self.conf.get('headers') == None:
5777
+           self.conf['headers'] = 1       # map default
5778
+       
5779
+       action1 = _("Enter the source file location:")
5780
+       action2 = _("Choose the target document type:")
5781
+       action3 = _("Some options you may check:")
5782
+       action4 = _("Some extra options:")
5783
+       checks_txt = {
5784
+           'headers'   : _("Include headers on output"),
5785
+           'enum-title': _("Number titles (1, 1.1, 1.1.1, etc)"),
5786
+           'toc'       : _("Do TOC also (Table of Contents)"),
5787
+           'mask-email': _("Hide e-mails from SPAM robots"),
5788
+       
5789
+           'toc-only'  : _("Just do TOC, nothing more"),
5790
+           'stdout'    : _("Dump to screen (Don't save target file)")
5791
+       }
5792
+       targets_menu = [TARGET_NAMES[x] for x in TARGETS]
5793
+       
5794
+       # Header
5795
+       self.label("%s %s"%(my_name.upper(), my_version),
5796
+           bg=self.bg2, fg=self.fg2).grid(columnspan=2, ipadx=10)
5797
+       self.label(_("ONE source, MULTI targets")+'\n%s\n'%my_url,
5798
+           bg=self.bg1, fg=self.fg1).grid(columnspan=2)
5799
+       self.row = 2
5800
+       # Choose input file
5801
+       self.action(action1) ; self.frame_open()
5802
+       e_infile = self.entry(textvariable=self.infile,width=25)
5803
+       e_infile.grid(row=self.row, column=0, sticky='e')
5804
+       if not self.infile.get(): e_infile.focus_set()
5805
+       self.button(_("Browse"), self.askfile).grid(
5806
+           row=self.row, column=1, sticky='w', padx=10)
5807
+       # Show outfile name, style and encoding (if any)
5808
+       txt = ''
5809
+       if outfile:
5810
+           txt = outfile
5811
+           if outfile == STDOUT: txt = _('<screen>')
5812
+           l_output = self.label(_('Output: ')+txt, fg=self.fg2, bg=self.bg2)
5813
+           l_output.grid(columnspan=2, sticky='w')
5814
+       for setting in ['style','encoding']:
5815
+           if self.conf.get(setting):
5816
+               name = setting.capitalize()
5817
+               val  = self.conf[setting]
5818
+               self.label('%s: %s'%(name, val),
5819
+                   fg=self.fg2, bg=self.bg2).grid(
5820
+                   columnspan=2, sticky='w')
5821
+       # Choose target
5822
+       self.frame_close() ; self.action(action2)
5823
+       self.frame_open()
5824
+       self.target_key2name()
5825
+       self.menu(self.target_name, targets_menu).grid(
5826
+           columnspan=2, sticky='w')
5827
+       # Options checkboxes label
5828
+       self.frame_close() ; self.action(action3)
5829
+       self.frame_open()
5830
+       # Compose options check boxes, example:
5831
+       # self.check(checks_txt['toc'],1,variable=self.f_toc)
5832
+       for check in self.checks:
5833
+           # Extra options label
5834
+           if check == 'toc-only':
5835
+               self.frame_close() ; self.action(action4)
5836
+               self.frame_open()
5837
+           txt = checks_txt[check]
5838
+           var = getattr(self, 'f_'+check)
5839
+           checked = self.conf.get(check)
5840
+           self.check(txt,checked,variable=var)
5841
+       self.frame_close()
5842
+       # Spacer and buttons
5843
+       self.label('').grid() ; self.row += 1
5844
+       b_quit = self.button(_("Quit"), self.exit)
5845
+       b_quit.grid(row=self.row, column=0, sticky='w', padx=30)
5846
+       b_conv = self.button(_("Convert!"), self.runprogram)
5847
+       b_conv.grid(row=self.row, column=1, sticky='e', padx=30)
5848
+       if self.target.get() and self.infile.get():
5849
+           b_conv.focus_set()
5850
+       
5851
+       # As documentation told me
5852
+       if sys.platform.startswith('win'):
5853
+           self.root.iconify()
5854
+           self.root.update()
5855
+           self.root.deiconify()
5856
+       
5857
+       self.root.mainloop()
5858
+
5859
+
5860
+##############################################################################
5861
+##############################################################################
5862
+
5863
+def exec_command_line(user_cmdline=[]):
5864
+   global CMDLINE_RAW, RC_RAW, DEBUG, VERBOSE, QUIET, GUI, Error
5865
+   
5866
+   # Extract command line data
5867
+   cmdline_data = user_cmdline or sys.argv[1:]
5868
+   CMDLINE_RAW = CommandLine().get_raw_config(cmdline_data, relative=1)
5869
+   cmdline_parsed = ConfigMaster(CMDLINE_RAW).parse()
5870
+   DEBUG   = cmdline_parsed.get('debug'  ) or 0
5871
+   VERBOSE = cmdline_parsed.get('verbose') or 0
5872
+   QUIET   = cmdline_parsed.get('quiet'  ) or 0
5873
+   GUI     = cmdline_parsed.get('gui'    ) or 0
5874
+   infiles = cmdline_parsed.get('infile' ) or []
5875
+   
5876
+   Message(_("Txt2tags %s processing begins")%my_version,1)
5877
+   
5878
+   # The easy ones
5879
+   if cmdline_parsed.get('help'   ): Quit(USAGE)
5880
+   if cmdline_parsed.get('version'): Quit(VERSIONSTR)
5881
+   if cmdline_parsed.get('targets'):
5882
+       listTargets()
5883
+       Quit()
5884
+
5885
+   # Multifile haters
5886
+   if len(infiles) > 1:
5887
+       errmsg=_("Option --%s can't be used with multiple input files")
5888
+       for option in NO_MULTI_INPUT:
5889
+           if cmdline_parsed.get(option):
5890
+               Error(errmsg%option)
5891
+   
5892
+   Debug("system platform: %s"%sys.platform)
5893
+   Debug("python version: %s"%(sys.version.split('(')[0]))
5894
+   Debug("line break char: %s"%repr(LB))
5895
+   Debug("command line: %s"%sys.argv)
5896
+   Debug("command line raw config: %s"%CMDLINE_RAW,1)
5897
+   
5898
+   # Extract RC file config
5899
+   if cmdline_parsed.get('rc') == 0:
5900
+       Message(_("Ignoring user configuration file"),1)
5901
+   else:
5902
+       rc_file = get_rc_path()
5903
+       if os.path.isfile(rc_file):
5904
+           Message(_("Loading user configuration file"),1)
5905
+           RC_RAW = ConfigLines(file_=rc_file).get_raw_config()
5906
+       
5907
+       Debug("rc file: %s"%rc_file)
5908
+       Debug("rc file raw config: %s"%RC_RAW,1)
5909
+   
5910
+   # Get all infiles config (if any)
5911
+   infiles_config = get_infiles_config(infiles)
5912
+   
5913
+   # Is GUI available?
5914
+   # Try to load and start GUI interface for --gui
5915
+   if GUI:
5916
+       try:
5917
+           load_GUI_resources()
5918
+           Debug("GUI resources OK (Tk module is installed)")
5919
+           winbox = Gui()
5920
+           Debug("GUI display OK")
5921
+           GUI = 1
5922
+       except:
5923
+           Debug("GUI Error: no Tk module or no DISPLAY")
5924
+           GUI = 0
5925
+   
5926
+   # User forced --gui, but it's not available
5927
+   if cmdline_parsed.get('gui') and not GUI:
5928
+       print(getTraceback()); print()
5929
+       Error(
5930
+           "Sorry, I can't run my Graphical Interface - GUI\n"
5931
+           "- Check if Python Tcl/Tk module is installed (Tkinter)\n"
5932
+           "- Make sure you are in a graphical environment (like X)")
5933
+   
5934
+   # Okay, we will use GUI
5935
+   if GUI:
5936
+       Message(_("We are on GUI interface"),1)
5937
+       
5938
+       # Redefine Error function to raise exception instead sys.exit()
5939
+       def Error(msg):
5940
+           showerror(_('txt2tags ERROR!'), msg)
5941
+           raise error
5942
+       
5943
+       # If no input file, get RC+cmdline config, else full config
5944
+       if not infiles:
5945
+           gui_conf = ConfigMaster(RC_RAW+CMDLINE_RAW).parse()
5946
+       else:
5947
+           try   : gui_conf = infiles_config[0][0]
5948
+           except: gui_conf = {}
5949
+       
5950
+       # Sanity is needed to set outfile and other things
5951
+       gui_conf = ConfigMaster().sanity(gui_conf, gui=1)
5952
+       Debug("GUI config: %s"%gui_conf,5)
5953
+       
5954
+       # Insert config and populate the nice window!
5955
+       winbox.load_config(gui_conf)
5956
+       winbox.mainwindow()
5957
+   
5958
+   # Console mode rocks forever!
5959
+   else:
5960
+       Message(_("We are on Command Line interface"),1)
5961
+       
5962
+       # Called with no arguments, show error
5963
+       # TODO#1: this checking should be only in ConfigMaster.sanity()
5964
+       if not infiles:
5965
+           Error(_('Missing input file (try --help)') + '\n\n' +
5966
+           _('Please inform an input file (.t2t) at the end of the command.') + '\n' +
5967
+           _('Example:') + ' %s -t html %s' % (my_name, _('file.t2t')))
5968
+       
5969
+       convert_this_files(infiles_config)
5970
+   
5971
+   Message(_("Txt2tags finished successfully"),1)
5972
+
5973
+if __name__ == '__main__':
5974
+   try:
5975
+       exec_command_line()
5976
+   except error as msg:
5977
+       sys.stderr.write("%s\n"%msg)
5978
+       sys.stderr.flush()
5979
+       sys.exit(1)
5980
+   except SystemExit:
5981
+       pass
5982
+   except:
5983
+       sys.stderr.write(getUnknownErrorMessage())
5984
+       sys.stderr.flush()
5985
+       sys.exit(1)
5986
+   Quit()
5987
+
5988
+# The End.
5989
tovid-0.35.0.tar.gz/libtovid/metagui/gui.py -> tovid-0.35.2.tar.gz/libtovid/metagui/gui.py Changed
12
 
1
@@ -95,7 +95,9 @@
2
         """
3
         text = self.stdin_text.get()
4
         # Write the entered text to the command's stdin pipe
5
-        self.command.proc.stdin.write(text + '\n')
6
+        #self.command.proc.stdin.write(text + '\n')
7
+        # python 3 compatibility
8
+        self.command.proc.stdin.write(bytearray(text + "\n", "ascii"))
9
         self.command.proc.stdin.flush()
10
         # Show what was typed in the log window
11
         self.write(text)
12
tovid-0.35.0.tar.gz/setup.py -> tovid-0.35.2.tar.gz/setup.py Changed
30
 
1
@@ -44,7 +44,7 @@
2
 # Current SVN version number
3
 #_tovid_version = svn_version()
4
 # Official release number
5
-_tovid_version = '0.35.0'
6
+_tovid_version = '0.35.2'
7
 
8
 
9
 import os
10
@@ -148,11 +148,18 @@
11
     def run(self):
12
         """Build the tovid manual page.
13
         """
14
+        # For python 3 txt2tags needs an unofficial script
15
+        import sys
16
+        if (sys.version_info > (3, 0)):
17
+            txt2tags = 'docs/scripts/txt2tags'
18
+        else:
19
+            txt2tags = 'txt2tags'
20
+
21
         # Build only if target does not exist, or if source is newer than target
22
         mod = os.path.getmtime
23
         if not os.path.exists(self.target) or (mod(self.source) > mod(self.target)):
24
             print("Rebuilding tovid manual page")
25
-            command = 'txt2tags -t man -i "%s" -o "%s"' % (self.source, self.target)
26
+            command = '%s -t man -i "%s" -o "%s"' % (txt2tags, self.source, self.target)
27
             os.system(command)
28
         else:
29
             print("Manual page already built, not building again")
30
tovid-0.35.0.tar.gz/src/idvid -> tovid-0.35.2.tar.gz/src/idvid Changed
42
 
1
@@ -455,11 +455,11 @@
2
     if $USE_NAVLOG; then
3
         if egrep -qi 'mpeg$|mpg$|vob$' <<< "${INFILE##*.}"; then
4
             ID_VIDEO_FRAMES=$(awk 'END{print NR}' "$NAV_LOG" )
5
-            V_DUR=$(bc <<< "$ID_VIDEO_FRAMES / $ID_VIDEO_FPS")
6
+            V_DUR=$( ${bC} <<< "$ID_VIDEO_FRAMES / $ID_VIDEO_FPS")
7
             V_DURATION=${V_DUR%%.*} # final value is integer ( seconds )
8
         else
9
             V_DURATION=$(awk '($2==1) { field = $NF }; END{ print field/1000 }' "$NAV_LOG")
10
-            ID_VIDEO_FRAMES=$(bc <<< "$V_DURATION * $ID_VIDEO_FPS")
11
+            ID_VIDEO_FRAMES=$( ${bC} <<< "$V_DURATION * $ID_VIDEO_FPS")
12
             ID_VIDEO_FRAMES=${ID_VIDEO_FRAMES%%.*}
13
             # final value is in seconds
14
             V_DURATION=${V_DURATION%%.*} # integer
15
@@ -531,7 +531,7 @@
16
             # infer bitrate from file size and duration
17
             v_size=$(( $(du -m "$INFILE" | awk '{ print $1 }') * 8192 ))
18
             if (( ${V_DURATION%.*} )); then
19
-                ID_VIDEO_BITRATE=$(bc -l <<< "$v_size / $V_DURATION")
20
+                ID_VIDEO_BITRATE=$( ${bC} -l <<< "$v_size / $V_DURATION")
21
                 ID_VIDEO_BITRATE=$(( v_size / V_DURATION ))000
22
                 #echo -e "Probed video bitrate not available, infering from file size and duration\n"
23
             fi
24
@@ -545,7 +545,7 @@
25
     if test_is_number $vid_frames && ((vid_frames)); then
26
         (( $ID_VIDEO_FRAMES == 0 )) && ID_VIDEO_FRAMES=$vid_frames
27
     elif  (( ${V_DURATION%.*} )) &&  (( ${ID_VIDEO_FPS/./} )); then
28
-        VIDEO_FRAMES=$(bc -l <<< "$V_DURATION * $ID_VIDEO_FPS")
29
+        VIDEO_FRAMES=$( ${bC} -l <<< "$V_DURATION * $ID_VIDEO_FPS")
30
         if (( $ID_VIDEO_FRAMES == 0 )); then
31
             ID_VIDEO_FRAMES=${VIDEO_FRAMES%.*}
32
             #echo -e "Probed frame count not available, infering from duration and framerate\n"
33
@@ -622,7 +622,7 @@
34
         echo "V_ASPECT_WIDTH=$V_ASPECT_WIDTH"
35
         echo "ID_VIDEO_FRAMES=$ID_VIDEO_FRAMES"
36
     elif $TABULAR; then
37
-        FILE_SIZE=$(du -Dh "$INFILE" | awk '{print $1}')
38
+        FILE_SIZE=$(du -Hh "$INFILE" | awk '{print $1}')
39
         echo "$INFILE||$FILE_SIZE||${ID_VIDEO_WIDTH}x${ID_VIDEO_HEIGHT}||$ID_VIDEO_FPS||$ID_VIDEO_BITRATE||$ID_AUDIO_BITRATE" >> "$TABLE"
40
     else
41
         echo $SEPARATOR
42
tovid-0.35.0.tar.gz/src/makedvd -> tovid-0.35.2.tar.gz/src/makedvd Changed
26
 
1
@@ -142,7 +142,7 @@
2
     else
3
         DISC_CAPACITY=0
4
     fi
5
-    DISC_CAPACITY=$(echo "$DISC_CAPACITY / 1024 / 1024" | bc)
6
+    DISC_CAPACITY=$(echo "$DISC_CAPACITY / 1024 / 1024" | ${bC} )
7
 
8
     # Define usable DVDs
9
     HAVE_DVD_RW=$(verify "$DISC_TYPE" set "DVD-RW DVD+RW")
10
@@ -308,12 +308,13 @@
11
     DISC_SUM=0
12
     while test $i -le $NUM_VOBS; do
13
       VOB=$(echo "$VOB_LIST" | awk -F ':' '{ print $'$i' }')
14
-      VOB_SIZE=$(du -D -B M "$VOB" | awk -F ' ' '{print $1}' | tr -d M)
15
+      VOB_SIZE=$(du -H -m "$VOB" | awk '{print $1}')
16
       DISC_SUM=$(expr $VOB_SIZE \+ $DISC_SUM)
17
       i=$(expr $i \+ 1)
18
     done
19
     OUTDIR=$(readlink -f "$OUT_DIR")
20
-    AVAIL_SPACE=$(df -B M -P "${OUTDIR%/*}" | awk 'NR != 1 {print $4;}' | tr -d M)
21
+    AVAIL_SPACE=$(df -P "$OUT_DIR" | awk 'NR==1 {sub("-blocks", "", $2); blocksize=$2} \
22
+      NR!=1 {print int($4/1024*blocksize/1024)}')
23
 
24
     if test $DISC_SUM -gt $AVAIL_SPACE; then
25
        echo $SEPARATOR
26
tovid-0.35.0.tar.gz/src/makempg -> tovid-0.35.2.tar.gz/src/makempg Changed
89
 
1
@@ -336,7 +336,7 @@
2
     # based on original file size
3
     $SLICE && VIDEO_DURATION=$CLIP_LENGTH || VIDEO_DURATION=$V_DURATION
4
     if test "$VIDEO_DURATION" = "0"; then
5
-        CUR_SIZE=$(du -Dck "$IN_FILE" | awk 'END{print $1}')
6
+        CUR_SIZE=$(du -Hck "$IN_FILE" | awk 'END{print $1}')
7
         NEED_SPACE=$(expr $CUR_SIZE \* 2)
8
     # Estimate space based as kbps * duration
9
     else
10
@@ -757,13 +757,13 @@
11
     test -n "$AVG_BITRATE" && AVG_BITRATE=$(expr $AVG_BITRATE \/ 1000)
12
     test -n "$PEAK_BITRATE" && PEAK_BITRATE=$(expr $PEAK_BITRATE \/ 1000)
13
     KB_PER_MIN=$(expr $FINAL_SIZE \* 60 \/ $V_DURATION \+ 1)
14
-    ENC_TIME_RATIO=$(echo "scale = 2; $SCRIPT_TOT_TIME / $V_DURATION" | bc)
15
+    ENC_TIME_RATIO=$(echo "scale = 2; $SCRIPT_TOT_TIME / $V_DURATION" | ${bC} )
16
     if $USE_FFMPEG; then
17
         BACKEND="$FFmpeg"
18
     else
19
         BACKEND="mpeg2enc"
20
     fi
21
-
22
+    [[ $CPU_SPEED ]] && MHZ=MHz || MHZ=
23
     # Final statistics string (pretty-printed)
24
     FINAL_STATS_PRETTY=`cat << EOF
25
     ----------------------------------------
26
@@ -775,7 +775,7 @@
27
     Target bitrate:  $VID_BITRATE kbits/sec
28
     Average bitrate: $AVG_BITRATE kbits/sec
29
     Peak bitrate:    $PEAK_BITRATE kbits/sec
30
-    Took $HHMMSS to encode on $CPU_MODEL $CPU_SPEED mhz
31
+    Took $HHMMSS to encode on $CPU_MODEL $CPU_SPEED $MHZ
32
     -----------------------------------------
33
 EOF`
34
 
35
@@ -1116,13 +1116,13 @@
36
     ((${CLIP_SEEK%.*} > 0)) && [[ -z $ASYNC ]] && ASYNC1="-async 1"
37
     if [[ "$CLIP_ENDTIME" ]]; then
38
         [[ "$CLIP_ENDTIME" = *:* ]] && CLIP_ENDTIME=$(unformat_time $CLIP_ENDTIME)
39
-        CLIP_LENGTH=$(echo "$CLIP_ENDTIME - $CLIP_SEEK" | bc)
40
+        CLIP_LENGTH=$(echo "$CLIP_ENDTIME - $CLIP_SEEK" | ${bC} )
41
         [[ ${CLIP_LENGTH%.*} -eq 0 ]] && CLIP_LENGTH=1
42
         FF_LENGTH="-t $CLIP_LENGTH"
43
     fi
44
     CLIP_SEEK="-ss $CLIP_SEEK"
45
 fi
46
-#    FRAMES=$(echo "scale = 2; $ID_VIDEO_FPS * $CLIP_ENDTIME" | bc)
47
+#    FRAMES=$(echo "scale = 2; $ID_VIDEO_FPS * $CLIP_ENDTIME" | ${bC} )
48
 #    MP_FRAMES="-frames ${FRAMES%.*}"
49
 
50
 
51
@@ -1133,7 +1133,7 @@
52
     yecho "Probing video for information. This may take several minutes..."
53
 
54
     # Get an MD5sum of the input file for statistics
55
-    IN_FILE_MD5=$(md5sum "$IN_FILE" | awk '{print $1}')
56
+    IN_FILE_MD5=$($md5sum "$IN_FILE" | awk '{print $1}')
57
 
58
     # Assume nothing is compliant unless idvid says so
59
     # (these will be overridden by idvid for compliant A/V)
60
@@ -1257,7 +1257,7 @@
61
     # When the audio is already compliant and the bitrate is known we
62
     # can calculate a more accurate size.
63
     if $AUDIO_OK && test "$ID_AUDIO_BITRATE" != "0"; then
64
-        AUD_BITRATE=$(echo "scale = 0; $ID_AUDIO_BITRATE / 1000" | bc)
65
+        AUD_BITRATE=$(echo "scale = 0; $ID_AUDIO_BITRATE / 1000" | ${bC} )
66
     fi
67
     AUDIO_SIZE=$(bc_math "$AUD_BITRATE * $LENGTH / (8 *1024)")
68
     VIDEO_SIZE=$(bc_math "$AUD_VID_SIZE - $AUDIO_SIZE")
69
@@ -1665,7 +1665,7 @@
70
 errors=$( $FFmpeg -i "$IN_FILE" -t 1  \
71
 -vf scale=w=720:h=352,pad=width=720:height=480:x=0:y=64,setdar=16/9 \
72
 -f null  -y /dev/null 2>&1)
73
-if grep -qE "Error.*\(width\|height\|setdar\|w=\|h=\)" <<< "$errors"; then
74
+if grep -qE "Error.*(width|height|setdar|w=|h=)" <<< "$errors"; then
75
     ff_legacy=1
76
 fi
77
 
78
@@ -2190,8 +2190,8 @@
79
 # ******************************************************************************
80
 
81
 if ! $FAKE; then
82
-    AUDIO_SIZE=$(du -c -b "$AUDIO_STREAM" | awk 'END{print $1}')
83
-    VIDEO_SIZE=$(du -c -b "$VIDEO_STREAM" | awk 'END{print $1}')
84
+    AUDIO_SIZE=$(ls -lnR "$AUDIO_STREAM" | awk 'END{print $5}')
85
+    VIDEO_SIZE=$(ls -lnR "$VIDEO_STREAM" | awk 'END{print $5}')
86
     # Total size of streams so far (in MBytes)
87
     STREAM_SIZE=$(expr \( $AUDIO_SIZE \+ $VIDEO_SIZE \) \/ 1000000)
88
     # If it exceeds disc size, add '%d' field to allow mplex to split output
89
tovid-0.35.0.tar.gz/src/todisc -> tovid-0.35.2.tar.gz/src/todisc Changed
327
 
1
@@ -80,7 +80,6 @@
2
 
3
 # check if symlink in /tmp exists and use time stamped link if so
4
 WORK_DIR="/tmp/todisc-work"
5
-
6
 LOG_FILE=$(readlink -f todisc.log)
7
 OUT_DIRECTORY=""
8
 TV_STANDARD=ntsc
9
@@ -332,6 +331,7 @@
10
 # Usage: continue_in [SECONDS]
11
 continue_in()
12
 {
13
+    local count LAST
14
     yecho ""
15
     (($1)) && LAST=$1 || LAST=5
16
     for ((i=LAST; i>=0; i--)); do
17
@@ -456,19 +456,19 @@
18
 # last 2 args are optional: defaults 'video' and the whole stream.
19
 stream_length()
20
 {
21
-    local end=""
22
+   local end=""
23
     local stream_type=video
24
     local ff_opts="-an -vcodec copy"
25
     [[ -n $2 ]] && stream_type=$2
26
     [[ -n $3 ]] && end="-t $3"
27
-    sed_var="{s/^.*time= *\([^ ]*\).*/\1/p}"
28
+    sed_var="{s/^.*time= *\([^ ]*\).*/\1/p;}"
29
     stream_name=$stream_type
30
     if [[ $stream_type = 'audio' ]]; then
31
         ff_opts="-vn -acodec copy"
32
     # workaround for avconv which is broken atm wrt getting m2v framerate right
33
     # overload stream_type to have another meaning, 
34
     elif [[ $stream_type = 'm2v' ]]; then
35
-        sed_var="{s/^.*frame= *\([^ ]*\).*/\1/p}"
36
+        sed_var="{s/^.*frame= *\([^ ]*\).*/\1/p;}"
37
         stream_name=video
38
     fi
39
     print2log "Using $FFmpeg to get accurate $stream_name length of $1"
40
@@ -598,9 +598,11 @@
41
 # usage: bc_math "expression" [int]
42
 bc_math()
43
 {
44
+    local val=$1
45
+    #val=${val//$'\n'/}
46
     OLC_ALL=$LC_ALL
47
     LC_ALL=C
48
-    bc_out=$(bc <<< "scale=3;$1" 2>/dev/null)
49
+    bc_out=$( ${bC} <<< "scale=3;$val" 2>/dev/null)
50
     if [[ -n $2 && $2 = "int" ]]; then
51
         echo ${bc_out%.*}
52
     else
53
@@ -967,7 +969,7 @@
54
     video_type=$3
55
     yecho ""
56
     yecho "$VIDEO_IN is not compliant - re-encoding \
57
-      $(bc <<< "$VIDEO_IN_SEEK + ${MENU_LEN[MENU_NUM-1]}" 2>/dev/null)
58
+      $( ${bC} <<< "$VIDEO_IN_SEEK + ${MENU_LEN[MENU_NUM-1]}" 2>/dev/null)
59
         second slice to DVD compliant file"
60
     yecho "This is not strictly necessary and will reduce quality, but it may"
61
     yecho "help with sync problems if using the same file for audio and video."
62
@@ -984,7 +986,7 @@
63
     yecho "Converting files to $TGT_CAPS format with 'makempg'"
64
     continue_in 5
65
     makempg $NO_ASK -in "$VIDEO_IN" \
66
-    -slice 0-$(bc <<< "$VIDEO_IN_SEEK + ${MENU_LEN[MENU_NUM-1]}" 2>/dev/null) \
67
+    -slice 0-$( ${bC} <<< "$VIDEO_IN_SEEK + ${MENU_LEN[MENU_NUM-1]}" 2>/dev/null) \
68
     -${TV_STANDARD} -${TARGET} -in "$VIDEO_IN" \
69
     -out "${VIDEO_IN}.enc" "${TOVID_OPTS[@]}"
70
     # See if output file exists
71
@@ -1039,7 +1041,7 @@
72
         done
73
     else
74
         for len in ${GROUP_VIDEO_LENGTHS[@]}; do
75
-            adjusted_length=$( bc <<< "scale=3; $len + $remainder" 2>/dev/null)
76
+            adjusted_length=$( ${bC} <<< "scale=3; $len + $remainder" 2>/dev/null)
77
             num_chapters=$( bc_math "$adjusted_length / $chapter_length" int )
78
             if (( num_chapters > 0)); then
79
                 chapt_len_array=( $( for ((t=0; t<num_chapters; t++)); do
80
@@ -1050,7 +1052,7 @@
81
                 chapter_points=$( running_total <<< ${chapt_len_array[@]} )
82
                 # remove trailing space
83
                 chapter_points=$(sed 's/[ \t]*$//' <<< $chapter_points)
84
-                remainder=$( bc <<< "$adjusted_length % $chapter_length" \
85
+                remainder=$( ${bC} <<< "$adjusted_length % $chapter_length" \
86
                 2>/dev/null)
87
                 (( ${nochapt[index]} )) && local group_chapters[x++]=0 ||
88
                 local group_chapters[x++]=$chapter_points
89
@@ -1353,7 +1355,7 @@
90
     MENUTITLES=( "${menutitles[@]}" )
91
     # some vars for vmgm menu, depending on presence of -static or -quick-nav
92
     # how many titlesets do we have ?
93
-    for i in "$@"; do [[ $i == -end-titleset ]] && ((count++)); done
94
+    for i in "$@"; do [[ $i == -end-titleset ]] && ((tscount++)); done
95
     VMGM_PAUSE=$PAUSE_TIME
96
     grep -q  -- -static  <<< "${VMGM_OPTS[@]}" && VMGM_PAUSE="inf"
97
     for i in ${!VMGM_OPTS[@]}; do
98
@@ -1422,7 +1424,7 @@
99
 fi)
100
 $(if $QUICK_NAV; then
101
     echo -e "        <button name=\"ActionLeft\">"
102
-    echo -e "        g5=${ALLTITLES[count-1]}; g3=$count; button=1024;"
103
+    echo -e "        g5=${ALLTITLES[tscount-1]}; g3=$tscount; button=1024;"
104
     echo -e "        jump vmgm menu entry title;</button>"
105
     echo -e "        <button name=\"ActionRight\">"
106
     echo -e "        g5=1; g3=1; button=1024;"
107
@@ -1485,7 +1487,7 @@
108
     done
109
     unset vmgmtitles
110
     get_menu_titles "${VMGM_OPTS[@]}"
111
-    if [[ -n ${VMGM_OPTS[@]} ]] && ((${#vmgmtitles[@]} != count)); then
112
+    if [[ -n ${VMGM_OPTS[@]} ]] && ((${#vmgmtitles[@]} != tscount)); then
113
         usage_error "Number of titleset titles must equal the number
114
          of titlesets. ( -vmgm ... -titles 'Title 1' 'Title 2' -end-vmgm )"
115
     fi
116
@@ -1499,14 +1501,14 @@
117
         yecho "One title for each titleset you are making."
118
         yecho "Any other appropriate todisc options for the vmgm menu \
119
         can be specified as well."
120
-        if  [[ ${#MENUTITLES[@]} -eq $count ]]; then
121
+        if  [[ ${#MENUTITLES[@]} -eq $tscount ]]; then
122
             yecho "Since -menu-title was supplied for each titleset: \
123
             these titleset titles will be used:"
124
             for t in "${MENUTITLES[@]}"; do echo "\"$t\""; done
125
             VMGM_OPTS=(-titles "${MENUTITLES[@]}")
126
         else
127
             VMGM_OPTS[0]="-titles"
128
-            for ((menu=1; menu<=count; menu++)); do
129
+            for ((menu=1; menu<=tscount; menu++)); do
130
                 VMGM_OPTS[menu]="Titleset $menu"
131
             done
132
         fi
133
@@ -1517,7 +1519,7 @@
134
     else
135
         unset vmgmtitles
136
         get_menu_titles "${VMGM_OPTS[@]}"
137
-        if ((${#vmgmtitles[@]} != 0)) && ((${#vmgmtitles[@]} != count)); then
138
+        if ((${#vmgmtitles[@]} != 0)) && ((${#vmgmtitles[@]} != tscount)); then
139
             usage_error "Number of titleset titles must equal the number
140
             of titlesets."
141
         fi
142
@@ -1546,7 +1548,7 @@
143
                     shift
144
                 done
145
                 titleset_cmd=( todisc -titleset-mode -basedir "$WORK_DIR" \
146
-                -title_count "$num_titles" -tset_num ${count}-${tset} \
147
+                -title_count "$num_titles" -tset_num ${tscount}-${tset} \
148
                 "${GEN_OPTS[@]}" $NO_CONFIRM_BACKUP "${TITLESET_OPTS[@]}" \
149
                 $vmgm_playall )
150
                 yecho
151
@@ -1659,14 +1661,14 @@
152
         clr1="$colr1"
153
     fi
154
 
155
-    mk_rtn_cmd=(convert -size 100x80 xc:none \
156
+    mk_rtn_cmd=(convert +antialias -size 100x80 xc:none \
157
     -strokewidth 1 -stroke "$colr2" -fill "$clr1" \
158
     -draw 'rectangle 0,0 70,62' \
159
     -fill "$colr2" -stroke none \
160
     -draw "polyline 40,10 40,50 10,30 40,10" \
161
     -draw "polyline 60,10 60,50 30,30 60,10" \
162
     -fill "$colr2" -draw "rectangle 6,10 10,50" \
163
-    -resize 30% -trim +repage +antialias "$outbutton")
164
+    -resize 30% -trim +repage "$outbutton")
165
     print2log "Running ${mk_rtn_cmd[@]}"
166
     "${mk_rtn_cmd[@]}"
167
     mogrify -channel A -threshold 50% "$outbutton"
168
@@ -1698,6 +1700,7 @@
169
     play_btn_dim=$(get_image_dim "$outbutton")
170
     play_btn_width=$(awk -Fx '{print $1}' <<< $play_btn_dim )
171
     play_btn_height=$(awk -Fx '{print $2}' <<< $play_btn_dim )
172
+    mogrify -channel A -threshold 50% "$outbutton"
173
 }
174
 
175
 check_menufile()
176
@@ -2115,16 +2118,16 @@
177
     index=$2
178
     outppm="$WORK_DIR/animenu/$(printf %06d%s $index .ppm)"
179
     if [[ $fade_type = "crossfade" ]]; then
180
-        value=$(bc -l <<< "scale=2; ($fade_slide + 1) * $fade_incr") >&2
181
+        value=$( ${bC} -l <<< "scale=2; ($fade_slide + 1) * $fade_incr") >&2
182
         fade_cmd=(composite -blend $value -depth 8 "$overlay_ppm" \
183
         "$base_ppm" "$outppm")
184
     elif [[ $fade_type = "fadein" ]]; then
185
-        value=$(bc -l <<< "scale=2; $fade_slide * $fade_incr") >&2
186
+        value=$( ${bC} -l <<< "scale=2; $fade_slide * $fade_incr") >&2
187
         fade_cmd=(composite -depth 8 "$base_ppm" "$WORK_DIR/black.ppm" \
188
         -blend ${value}% "$outppm")
189
     elif [[ $fade_type = "fadeout" ]]; then
190
-        value=$(bc -l <<< "scale=2;100 - (($fade_slide + 1) * $fade_incr)") >&2
191
-        (( $(bc <<< "$value < 0") == 1 )) && value=0
192
+        value=$( ${bC} -l <<< "scale=2;100 - (($fade_slide + 1) * $fade_incr)") >&2
193
+        (( $( ${bC} <<< "$value < 0") == 1 )) && value=0
194
         fade_cmd=(composite -depth 8 "$base_ppm" "$WORK_DIR/black.ppm" \
195
         -blend ${value}% "$outppm")
196
     fi
197
@@ -3558,8 +3561,7 @@
198
 # check for multiple cpus if -jobs not passed already
199
 #TODO always wait for either 1 or 2 processes - no need for if block later
200
 if [[ -z $JOBS ]]; then
201
-    proc_cnt=$(grep ^processor /proc/cpuinfo |awk 'END{print $NF+1}')
202
-    max_procs=$proc_cnt
203
+    max_procs=$cpu_count # cpu_count is sourced from tovid-init
204
 fi
205
 
206
 if $BURN; then
207
@@ -3683,7 +3685,13 @@
208
 
209
 # Make sure -out was provided and it is valid
210
 if test -n "$OUT_DIRECTORY"; then
211
+    # for BSD readlink
212
+    if [[ ! -d "$OUT_DIRECTORY" ]]; then
213
+        mkdir "$OUT_DIRECTORY" || usage_error "Can not make $OUT_DIRECTORY"
214
+   bsdoutdir=1
215
+    fi
216
     OUT_DIR=$(readlink -f "$OUT_DIRECTORY")
217
+    ((bsdoutdir)) && rmdir "$OUT_DIRECTORY"
218
     if [[ ! -d ${OUT_DIR%/*} ]]; then
219
         OUT_PATH=$(readlink -m "$OUT_DIRECTORY")
220
         usage_error "The -out path ${OUT_PATH%/*}/ does not exist"
221
@@ -5014,7 +5022,7 @@
222
         SHORTFILE=:
223
     else
224
         FRAME_CK=$(stream_length "${IN_FILES[i]}" video 90)
225
-        [[ $(bc -l <<< "$FRAME_CK < 2") -eq 1 ]] && SHORTFILE=:
226
+        [[ $( ${bC} -l <<< "$FRAME_CK < 2") -eq 1 ]] && SHORTFILE=:
227
     fi
228
     if $SHORTFILE; then
229
         ! $USER_SEEK_VAL && SEEK_VAL[i]=0
230
@@ -7258,7 +7266,7 @@
231
     BG_AUDIOLENGTH=$(stream_length "$BG_AUDIO" audio)
232
 
233
     # make sure user isn't trying to get a longer menu than the audio allows
234
-    if [[ $(bc <<< "${MENU_LEN[MENU_NUM-1]} \
235
+    if [[ $( ${bC} <<< "${MENU_LEN[MENU_NUM-1]} \
236
     > $BG_AUDIOLENGTH" 2>/dev/null)  -eq 1 ]]; then
237
         MENU_AUDIOLEN=$BG_AUDIOLENGTH
238
     fi
239
@@ -7278,10 +7286,10 @@
240
     TT=1 # a constant value atm
241
     $SLIDE_FADE && MIX_SLIDE_LEN=$(bc_math "$MIX_SLIDE_LEN - $TT")
242
 
243
-    if [[ $(bc -l <<< "$MIX_SLIDE_LEN == 0") -eq 1 ]]; then
244
+    if [[ $( ${bC} -l <<< "$MIX_SLIDE_LEN == 0") -eq 1 ]]; then
245
         # use 2 frames for each still so MIX_SLIDE_LEN is not 0
246
-        MIX_SLIDE_LEN=$(bc -l <<< "scale=3; 2 / $FRAME_RATE")
247
-    elif [[ $(bc -l <<<  "$MIX_SLIDE_LEN < 0") -eq 1 ]]; then
248
+        MIX_SLIDE_LEN=$( ${bC} -l <<< "scale=3; 2 / $FRAME_RATE")
249
+    elif [[ $( ${bC} -l <<<  "$MIX_SLIDE_LEN < 0") -eq 1 ]]; then
250
         runtime_error "The menu length is not long enough for an animated menu.
251
         For slideshows where -bgaudio FILE is supplied, this is determined by:
252
         1. -menu-length argument if supplied
253
@@ -7389,12 +7397,12 @@
254
 
255
     if [[ $EFFECT = "fade" ]]; then
256
         [[ $TV_STANDARD = "ntsc" ]] && fade_frames=15 || fade_frames=12
257
-        fade_incr=$(bc -l <<< "scale=2; 100 / $fade_frames") >&2
258
+        fade_incr=$( ${bC} -l <<< "scale=2; 100 / $fade_frames") >&2
259
         convert -size ${CAROUSEL_SIZE}! xc:'#101010' -depth 8 \
260
         "$WORK_DIR/black.ppm"
261
     elif [[ $EFFECT = "crossfade" ]]; then
262
         [[ $TV_STANDARD = "ntsc" ]] && fade_frames=30 || fade_frames=25
263
-        fade_incr=$(bc -l <<< "scale=2; 100 / $fade_frames") >&2
264
+        fade_incr=$( ${bC} -l <<< "scale=2; 100 / $fade_frames") >&2
265
     fi
266
 
267
     TOYUV_FADE_CMD=(ppmtoy4m -v 0 -n $fade_frames -A $PIXEL_AR -F $YUV_FR -I p \
268
@@ -7622,7 +7630,7 @@
269
     fi
270
     # add -force to makevcd if short file
271
     # wait for input on short files (slides) unless -video-pause passed
272
-    if [[ $(bc -l <<< "${VID_LEN[i]} < 1") -eq 1 ]]; then
273
+    if [[ $( ${bC} -l <<< "${VID_LEN[i]} < 1") -eq 1 ]]; then
274
         [[ -z ${VPAUSE[i]} ]] && VPAUSE[i]="inf"
275
         # 1 chapter per short file, (altered below if group short file)
276
         ! $USER_CHAPTERS && CHAPTERS[i]=1 # each 'slide' is a chapter
277
@@ -7648,7 +7656,7 @@
278
                 GROUP_VID_LENGTHS[i]="${GROUP_VID_LENGTHS[i]} \
279
                 ${GROUP_VID_LEN[t]}"
280
                 # if short file, assume it is a slideshow, and use pause="inf"
281
-                if [[ $(bc -l <<< "${GROUP_VID_LEN[t]} < 1") -eq 1 ]]; then
282
+                if [[ $( ${bC} -l <<< "${GROUP_VID_LEN[t]} < 1") -eq 1 ]]; then
283
                     # but only if -group-video-pause was not passed
284
                     [[ -z ${GRP_VPAUSE[i]} ]] && GRP_VPAUSE[i]="inf"
285
                     ! $USER_CHAPTERS && CHAPTERS[i]=0 # each slide's a chapter
286
@@ -7683,7 +7691,7 @@
287
     let vid=MENU_NUM-1
288
     SHOWCASE_SEEK_VAL=${SEEK_VAL[vid]}
289
     # use silence if a short file ( probably a slide ) and no background audio
290
-    if [[ -z $BG_AUDIO &&  $( bc -l <<< "${VID_LEN[vid]} < 1") -eq 1 ]]; then
291
+    if [[ -z $BG_AUDIO &&  $( ${bC} -l <<< "${VID_LEN[vid]} < 1") -eq 1 ]]; then
292
         BG_AUDIO="none"
293
     fi
294
     # if no audio is detected in the video
295
@@ -7706,11 +7714,11 @@
296
                 ! $USER_BG_AUDIO_SEEK && BG_AUDIO_SEEK=0
297
                 # make sure MENU_AUDIOLEN value isn't longer than the video
298
                 # FIXME if video shorter than menu length adjust MENU_LEN
299
-                [[ $( bc -l <<< "$MENU_AUDIOLEN > ${VID_LEN[vid]}") -eq 1 ]] \
300
+                [[ $( ${bC} -l <<< "$MENU_AUDIOLEN > ${VID_LEN[vid]}") -eq 1 ]] \
301
                                             && MENU_AUDIOLEN=${VID_LEN[vid]}
302
                 # MENU_LEN can't be longer than the audio length
303
                 # don't use fade unless the video is long enough to support it
304
-                [[ $(bc -l <<< "${VID_LEN[vid]} < (($FADE * 2) + 2)") \
305
+                [[ $( ${bC} -l <<< "${VID_LEN[vid]} < (($FADE * 2) + 2)") \
306
                 -eq 1 ]] && AUDIO_FADE=false
307
             else
308
                 # same seek value as video unless user passes -bgaudio-seek
309
@@ -8687,7 +8695,7 @@
310
                 fi
311
             fi
312
             # SM_LOOPS is the # of frames for static menus
313
-            SM_LOOPS[i]=$( bc \
314
+            SM_LOOPS[i]=$( ${bC} \
315
              <<< "${SUBMENU_AUDIOLEN[i]} * $FRAME_RATE" 2>/dev/null)
316
             SM_LOOPS[i]=${SM_LOOPS[i]%.*}
317
         done
318
@@ -9629,7 +9637,7 @@
319
 if $STATIC; then
320
     # we have a value for MENU_AUDIOLEN AND BG_AUDIO
321
     if [[ -n "$BG_AUDIO" && "$BG_AUDIO" != "none" ]] && ! $MENU_FADE; then
322
-        LOOPS=$( bc <<< "$MENU_AUDIOLEN * $FRAME_RATE" 2>/dev/null)
323
+        LOOPS=$( ${bC} <<< "$MENU_AUDIOLEN * $FRAME_RATE" 2>/dev/null)
324
         LOOPS=${LOOPS%.*}
325
     # switched menu: no bg audio or video and not menu fade
326
     elif $SWITCHED && [[ -z $BG_VIDEO && -z $BG_AUDIO ]] && ! $MENU_FADE; then
327
tovid-0.35.0.tar.gz/src/todisc-fade-routine -> tovid-0.35.2.tar.gz/src/todisc-fade-routine Changed
18
 
1
@@ -211,14 +211,14 @@
2
 
3
 init_gamma_array ()
4
 {
5
-bc -l <<BC_EOF
6
+${bC} -l <<BC_EOF
7
 pi=4*a(1);
8
 
9
 start_frame=0
10
 
11
 # Get values from standard in
12
 # Format:
13
-# echo "29.97\n 300\n 10\n .1\n 5\n .05\n .1\n" | bc -l
14
+# echo "29.97\n 300\n 10\n .1\n 5\n .05\n .1\n" | ${bC} -l
15
 frame_rate=$FRAME_RATE;
16
 end_frame=$ANIMENU_ENDFRAME;
17
 average=$1;
18
tovid-0.35.0.tar.gz/src/tovid-init -> tovid-0.35.2.tar.gz/src/tovid-init Changed
172
 
1
@@ -45,7 +45,7 @@
2
 #set -u
3
 
4
 # Suite version
5
-TOVID_VERSION="0.35.0"
6
+TOVID_VERSION="0.35.2"
7
 
8
 # String used to separate blocks of output
9
 SEPARATOR="========================================================="
10
@@ -55,6 +55,7 @@
11
 TOVID_FORUMS="http://groups.google.com/group/tovid-users"
12
 TOVID_ISSUES="https://github.com/tovid-suite/tovid/issues"
13
 
14
+
15
 # ******************************************************************************
16
 # ******************************************************************************
17
 #
18
@@ -190,7 +191,7 @@
19
     HMS_SECS=$(awk -F ':' '{print $3}' <<< $1)
20
     # allow integer to be passed, if so it will be echoed unchanged
21
     if [[ $1 = *:* ]]; then
22
-        TOT_SECONDS=$(bc <<< "($HMS_HOURS * 3600) + ($HMS_MINS * 60) + $HMS_SECS")
23
+        TOT_SECONDS=$( ${bC} <<< "($HMS_HOURS * 3600) + ($HMS_MINS * 60) + $HMS_SECS")
24
     else
25
         TOT_SECONDS=$1
26
     fi
27
@@ -281,7 +282,7 @@
28
     # Wait for input file to appear
29
     # After a 30-second timeout, exit gracefully
30
     CUR_TIME=30
31
-    while test $CUR_TIME -gt 0; do 
32
+    while test $CUR_TIME -gt 0; do
33
         sleep 3
34
         # If file exists, wait a few more seconds, then break out
35
         if test -e "$FOP_OUTFILE"; then
36
@@ -304,7 +305,8 @@
37
 
38
     # File size in bytes
39
     FOP_LAST_SIZE=0
40
-    FOP_CUR_SIZE=$(du -b "$FOP_OUTFILE" | awk '{print $1}')
41
+    # BSD compatibiity, yes I know parsing ls is bad
42
+    FOP_CUR_SIZE=$(ls -lnR "$FOP_OUTFILE" | awk 'END{print $5}')
43
 
44
     # Keep looping until outfile stops getting bigger
45
     while test "$FOP_CUR_SIZE" -gt "$FOP_LAST_SIZE"; do
46
@@ -323,11 +325,11 @@
47
             "$ANIM_STR" "$FOP_MSG" "$FOP_CUR_MB" "$FOP_BASENAME_NAME"
48
 
49
         # Doze a bit to let the file size increase
50
-        # (SLEEP_TIME defaults to 1s if unset)
51
-        sleep ${SLEEP_TIME-"1"}
52
+        # freebsd couldn't handle ${SLEEP_TIME-1} so leave at 1s
53
+        sleep 1
54
 
55
         FOP_LAST_SIZE=$FOP_CUR_SIZE
56
-        FOP_CUR_SIZE=$(du -b "$FOP_OUTFILE" | awk '{print $1}')
57
+        FOP_CUR_SIZE=$(ls -lnR "$FOP_OUTFILE" | awk 'END{print $5}')
58
     done
59
     $QUIET && printf "\n" || printf "\n\n"
60
 }
61
@@ -398,7 +400,7 @@
62
 bc_math()
63
 # usage: bc_math "expression" [int]
64
 {
65
-    bc_out=$(bc <<< "scale=3;$1" 2>/dev/null)
66
+    bc_out=$( ${bC} <<< "scale=3;$1" 2>/dev/null)
67
     if [[ -n $2 && $2 = "int" ]]; then
68
         echo ${bc_out%.*}
69
     else
70
@@ -455,6 +457,25 @@
71
     printf "\n"
72
 }
73
 
74
+# BSD's readlink behaves differently than GNU's. Use python instead
75
+# This is just a replacement for readlink -f which is used in our scripts,
76
+# though it could be adapted for other options easily enough.
77
+if [[ $(uname -s) =~ BSD ]]; then
78
+    readlink () 
79
+    { 
80
+        local args out parent_dir;
81
+        args=();
82
+        for arg in "$@"; do
83
+            case "$arg" in 
84
+                -[a-zA-Z0-9]) ;;
85
+                *) args+=($arg) ;;
86
+            esac;
87
+        done;
88
+        out="\"${args[*]}\"";
89
+        python -c "import os.path; print os.path.realpath($out)"
90
+    }
91
+fi
92
+
93
 # ******************************************************************************
94
 #
95
 #
96
@@ -476,15 +497,28 @@
97
     /proc/cpuinfo | head -n 1 | sed 's/^  *//g')
98
     CPU_SPEED=$(awk 'BEGIN { IGNORECASE = 1 } /MHz/ { print $4 }' /proc/cpuinfo | head -n 1)
99
     # Test for multiple CPUs. If they are available, try to use them.
100
-    if test $(grep "^processor" /proc/cpuinfo | wc -l) -ge "2"; then
101
-        MULTIPLE_CPUS=:
102
-    else
103
-        MULTIPLE_CPUS=false
104
-    fi
105
+    cpu_count=$(grep "^processor" /proc/cpuinfo | wc -l)
106
+    ((cpu_count > 1)) && MULTIPLE_CPUS=: || MULTIPLE_CPUS=false
107
 elif test "$KERNEL" = "Darwin"; then
108
-    :
109
+    (( $(sysctl -n hw.ncpu) > 1 )) && MULTIPLE_CPUS=: || MULTIPLE_CPUS=false
110
+elif [[ $KERNEL =~ BSD ]]; then
111
+    cpu_count=$(sysctl hw.ncpu | awk '{print $2}')
112
+    ((cpu_count > 1)) && MULTIPLE_CPUS=:
113
+    CPU_MODEL=$(sysctl  hw.model |sed 's/.*: \(.*\)@/\1/')
114
+    CPU_SPEED=''
115
 fi
116
 
117
+# use gnubc on bsd systems (found in /usr/local)
118
+# bsd uses md5, which needs -r to print hash in 1st column
119
+if [[ $KERNEL =~ 'BSD' ]]; then
120
+    bC=/usr/local/bin/bc
121
+    md5=md5
122
+    md5sum="md5 -r"
123
+else
124
+    bC=$(which bc)
125
+    md5=md5sum
126
+    md5sum=md5sum
127
+fi
128
 
129
 # ******************************************************************************
130
 # Find multiple version kludge
131
@@ -558,10 +592,19 @@
132
 [[ $TOVID_OUTPUT_DIR ]] && OUTPUT_DIR="$TOVID_WORKING_DIR"
133
 [[ $TOVID_FFMPEG_CMD ]] && TOVID_FFMPEG="$TOVID_FFMPEG_CMD"
134
 # FFmpeg and FFprobe are vars used for ffmpeg by scripts needing ffmpeg/avconv
135
-# if avconv is installed, use that unless env var set
136
-hash avconv 2>/dev/null && TOVID_FFMPEG=${TOVID_FFMPEG:-avconv}
137
-hash avprobe 2>/dev/null && TOVID_FFPROBE=${TOVID_FFPROBE:=avprobe}
138
+# if ffmpeg is installed, use that unless env var set
139
+if hash ffmpeg 2>/dev/null; then
140
+    TOVID_FFMPEG=${TOVID_FFMPEG:-ffmpeg}
141
+elif hash avconv 2>/dev/null; then
142
+    TOVID_FFMPEG=${TOVID_FFMPEG:-avconv}
143
+fi
144
+if hash ffprobe 2>/dev/null; then
145
+    TOVID_FFPROBE=${TOVID_FFPROBE:=ffprobe}
146
+elif hash ffprobe 2>/dev/null; then
147
+    TOVID_FFPROBE=${TOVID_FFPROBE:=avprobe}
148
+fi
149
 # finally, default to ffmpeg if non of the above override it
150
+# this will cause the assert_dep to recommend installing ffmpeg
151
 FFmpeg=${TOVID_FFMPEG:=ffmpeg}
152
 [[ $FFmpeg =~ ffmpeg ]] && TOVID_FFPROBE=ffprobe
153
 [[ $FFmpeg =~ avconv ]] && TOVID_FFPROBE=avprobe
154
@@ -593,7 +636,7 @@
155
     # *************************************************************************
156
     # Required Dependencies
157
     # *************************************************************************
158
-    core="grep sed md5sum mplayer mplex mpeg2enc yuvfps yuvdenoise ppmtoy4m mp2enc jpeg2yuv"
159
+    core="grep sed $md5 mplayer mplex mpeg2enc yuvfps yuvdenoise ppmtoy4m mp2enc jpeg2yuv"
160
 
161
     # *************************************************************************
162
     # Optional Dependencies
163
@@ -633,7 +676,7 @@
164
     # Quit and complain if ANY core dependency is missing.
165
     assert_dep "$core" "You are missing CORE tovid dependencies!"
166
     # ffmpeg is also a part of core deps, but is taken care of here
167
-    ffmpeg_alts="Use either ffmpeg (ffmpeg.org) or avconv (libav.org)."
168
+    ffmpeg_alts="Use ffmpeg from ffmpeg.org (recommended), or avconv from libav.org."
169
     ffmpeg_pref="Set choice in ${USER_PREFS}. As in: TOVID_FFMPEG=ffmpeg"
170
     assert_dep $FFmpeg "You are missing $FFmpeg ! $ffmpeg_alts ${ffmpeg_pref}."
171
 
172
tovid-0.35.0.tar.gz/src/tovid-init.in -> tovid-0.35.2.tar.gz/src/tovid-init.in Changed
163
 
1
@@ -55,6 +55,7 @@
2
 TOVID_FORUMS="http://groups.google.com/group/tovid-users"
3
 TOVID_ISSUES="https://github.com/tovid-suite/tovid/issues"
4
 
5
+
6
 # ******************************************************************************
7
 # ******************************************************************************
8
 #
9
@@ -190,7 +191,7 @@
10
     HMS_SECS=$(awk -F ':' '{print $3}' <<< $1)
11
     # allow integer to be passed, if so it will be echoed unchanged
12
     if [[ $1 = *:* ]]; then
13
-        TOT_SECONDS=$(bc <<< "($HMS_HOURS * 3600) + ($HMS_MINS * 60) + $HMS_SECS")
14
+        TOT_SECONDS=$( ${bC} <<< "($HMS_HOURS * 3600) + ($HMS_MINS * 60) + $HMS_SECS")
15
     else
16
         TOT_SECONDS=$1
17
     fi
18
@@ -281,7 +282,7 @@
19
     # Wait for input file to appear
20
     # After a 30-second timeout, exit gracefully
21
     CUR_TIME=30
22
-    while test $CUR_TIME -gt 0; do 
23
+    while test $CUR_TIME -gt 0; do
24
         sleep 3
25
         # If file exists, wait a few more seconds, then break out
26
         if test -e "$FOP_OUTFILE"; then
27
@@ -304,7 +305,8 @@
28
 
29
     # File size in bytes
30
     FOP_LAST_SIZE=0
31
-    FOP_CUR_SIZE=$(du -b "$FOP_OUTFILE" | awk '{print $1}')
32
+    # BSD compatibiity, yes I know parsing ls is bad
33
+    FOP_CUR_SIZE=$(ls -lnR "$FOP_OUTFILE" | awk 'END{print $5}')
34
 
35
     # Keep looping until outfile stops getting bigger
36
     while test "$FOP_CUR_SIZE" -gt "$FOP_LAST_SIZE"; do
37
@@ -323,11 +325,11 @@
38
             "$ANIM_STR" "$FOP_MSG" "$FOP_CUR_MB" "$FOP_BASENAME_NAME"
39
 
40
         # Doze a bit to let the file size increase
41
-        # (SLEEP_TIME defaults to 1s if unset)
42
-        sleep ${SLEEP_TIME-"1"}
43
+        # freebsd couldn't handle ${SLEEP_TIME-1} so leave at 1s
44
+        sleep 1
45
 
46
         FOP_LAST_SIZE=$FOP_CUR_SIZE
47
-        FOP_CUR_SIZE=$(du -b "$FOP_OUTFILE" | awk '{print $1}')
48
+        FOP_CUR_SIZE=$(ls -lnR "$FOP_OUTFILE" | awk 'END{print $5}')
49
     done
50
     $QUIET && printf "\n" || printf "\n\n"
51
 }
52
@@ -398,7 +400,7 @@
53
 bc_math()
54
 # usage: bc_math "expression" [int]
55
 {
56
-    bc_out=$(bc <<< "scale=3;$1" 2>/dev/null)
57
+    bc_out=$( ${bC} <<< "scale=3;$1" 2>/dev/null)
58
     if [[ -n $2 && $2 = "int" ]]; then
59
         echo ${bc_out%.*}
60
     else
61
@@ -455,6 +457,25 @@
62
     printf "\n"
63
 }
64
 
65
+# BSD's readlink behaves differently than GNU's. Use python instead
66
+# This is just a replacement for readlink -f which is used in our scripts,
67
+# though it could be adapted for other options easily enough.
68
+if [[ $(uname -s) =~ BSD ]]; then
69
+    readlink () 
70
+    { 
71
+        local args out parent_dir;
72
+        args=();
73
+        for arg in "$@"; do
74
+            case "$arg" in 
75
+                -[a-zA-Z0-9]) ;;
76
+                *) args+=($arg) ;;
77
+            esac;
78
+        done;
79
+        out="\"${args[*]}\"";
80
+        python -c "import os.path; print os.path.realpath($out)"
81
+    }
82
+fi
83
+
84
 # ******************************************************************************
85
 #
86
 #
87
@@ -476,15 +497,28 @@
88
     /proc/cpuinfo | head -n 1 | sed 's/^  *//g')
89
     CPU_SPEED=$(awk 'BEGIN { IGNORECASE = 1 } /MHz/ { print $4 }' /proc/cpuinfo | head -n 1)
90
     # Test for multiple CPUs. If they are available, try to use them.
91
-    if test $(grep "^processor" /proc/cpuinfo | wc -l) -ge "2"; then
92
-        MULTIPLE_CPUS=:
93
-    else
94
-        MULTIPLE_CPUS=false
95
-    fi
96
+    cpu_count=$(grep "^processor" /proc/cpuinfo | wc -l)
97
+    ((cpu_count > 1)) && MULTIPLE_CPUS=: || MULTIPLE_CPUS=false
98
 elif test "$KERNEL" = "Darwin"; then
99
-    :
100
+    (( $(sysctl -n hw.ncpu) > 1 )) && MULTIPLE_CPUS=: || MULTIPLE_CPUS=false
101
+elif [[ $KERNEL =~ BSD ]]; then
102
+    cpu_count=$(sysctl hw.ncpu | awk '{print $2}')
103
+    ((cpu_count > 1)) && MULTIPLE_CPUS=:
104
+    CPU_MODEL=$(sysctl  hw.model |sed 's/.*: \(.*\)@/\1/')
105
+    CPU_SPEED=''
106
 fi
107
 
108
+# use gnubc on bsd systems (found in /usr/local)
109
+# bsd uses md5, which needs -r to print hash in 1st column
110
+if [[ $KERNEL =~ 'BSD' ]]; then
111
+    bC=/usr/local/bin/bc
112
+    md5=md5
113
+    md5sum="md5 -r"
114
+else
115
+    bC=$(which bc)
116
+    md5=md5sum
117
+    md5sum=md5sum
118
+fi
119
 
120
 # ******************************************************************************
121
 # Find multiple version kludge
122
@@ -558,10 +592,19 @@
123
 [[ $TOVID_OUTPUT_DIR ]] && OUTPUT_DIR="$TOVID_WORKING_DIR"
124
 [[ $TOVID_FFMPEG_CMD ]] && TOVID_FFMPEG="$TOVID_FFMPEG_CMD"
125
 # FFmpeg and FFprobe are vars used for ffmpeg by scripts needing ffmpeg/avconv
126
-# if avconv is installed, use that unless env var set
127
-hash avconv 2>/dev/null && TOVID_FFMPEG=${TOVID_FFMPEG:-avconv}
128
-hash avprobe 2>/dev/null && TOVID_FFPROBE=${TOVID_FFPROBE:=avprobe}
129
+# if ffmpeg is installed, use that unless env var set
130
+if hash ffmpeg 2>/dev/null; then
131
+    TOVID_FFMPEG=${TOVID_FFMPEG:-ffmpeg}
132
+elif hash avconv 2>/dev/null; then
133
+    TOVID_FFMPEG=${TOVID_FFMPEG:-avconv}
134
+fi
135
+if hash ffprobe 2>/dev/null; then
136
+    TOVID_FFPROBE=${TOVID_FFPROBE:=ffprobe}
137
+elif hash ffprobe 2>/dev/null; then
138
+    TOVID_FFPROBE=${TOVID_FFPROBE:=avprobe}
139
+fi
140
 # finally, default to ffmpeg if non of the above override it
141
+# this will cause the assert_dep to recommend installing ffmpeg
142
 FFmpeg=${TOVID_FFMPEG:=ffmpeg}
143
 [[ $FFmpeg =~ ffmpeg ]] && TOVID_FFPROBE=ffprobe
144
 [[ $FFmpeg =~ avconv ]] && TOVID_FFPROBE=avprobe
145
@@ -593,7 +636,7 @@
146
     # *************************************************************************
147
     # Required Dependencies
148
     # *************************************************************************
149
-    core="grep sed md5sum mplayer mplex mpeg2enc yuvfps yuvdenoise ppmtoy4m mp2enc jpeg2yuv"
150
+    core="grep sed $md5 mplayer mplex mpeg2enc yuvfps yuvdenoise ppmtoy4m mp2enc jpeg2yuv"
151
 
152
     # *************************************************************************
153
     # Optional Dependencies
154
@@ -633,7 +676,7 @@
155
     # Quit and complain if ANY core dependency is missing.
156
     assert_dep "$core" "You are missing CORE tovid dependencies!"
157
     # ffmpeg is also a part of core deps, but is taken care of here
158
-    ffmpeg_alts="Use either ffmpeg (ffmpeg.org) or avconv (libav.org)."
159
+    ffmpeg_alts="Use ffmpeg from ffmpeg.org (recommended), or avconv from libav.org."
160
     ffmpeg_pref="Set choice in ${USER_PREFS}. As in: TOVID_FFMPEG=ffmpeg"
161
     assert_dep $FFmpeg "You are missing $FFmpeg ! $ffmpeg_alts ${ffmpeg_pref}."
162
 
163
Refresh

No build results available

Refresh

No rpmlint results available

Request History
Luigi Baldoni's avatar

Aloysius created request about 6 years ago

- Update to version 0.35.2
* Fixed set_chapters not having exec bit set
* Fixed grep for libav filters
* Some python3 fixes
* Fixed scope problem that only showed up on freebsd for some
reason.
* Fixed imagemagick spumux buttons for IM-6.9.1-x.
* Make ffmpeg the default encoder when both ffmpeg and avconv
are present.


Olaf Hering's avatar

olh accepted request about 6 years ago