1#
2#
3# Librairie de fonctions TCL pour la g�n�ration de tableaux
4#
5# Exemple d'utilisation
6#
7#	set style { ... }
8#	set data {}
9#	for ...
10#		lappend data [list pattern val1 val2 ... valn]
11#	puts [::arrgen::output "html" $style $data]
12#
13# Ou :
14#
15#	set style { ... }
16#	if {[::arrgen::parse tabstyle $style msg] == -1} then {
17#		puts stderr $msg
18#	}
19#	set data {}
20#	for ...
21#		lappend data [list pattern val1 val2 ... valn]
22#	puts [::arrgen::output "html" tabstyle $data]
23#
24# Langage des styles
25#   - global
26#	- chars
27#	    <int> (normal | bold | italic)+
28#	- color
29#	    <hex> | transparent
30#       - align
31#	    left | right | center | justify
32#	- botbar
33#	    yes | no
34#	- format
35#	    raw | cooked | lines | <procedure>
36#	- columns
37#	    <int>+
38#	- csv
39#	    - separator
40#		<character>
41#	- latex
42#	    - linewidth
43#		<float>
44#	    - bordersep
45#		<float>
46#   - pattern <nom>
47#	- chars
48#	    <int> (normal | bold | italic)+
49#	- color
50#	    <hex> | transparent
51#       - align
52#	    left | right | center | justify
53#	- botbar
54#	    yes | no
55#	- format
56#	    raw | cooked | lines | <procedure>
57#	- topbar
58#	    yes | no
59#	- title
60#	    yes | no
61#	- vbar
62#	    yes | no
63#	- column
64#	    - chars
65#		<int> (normal | bold | italic)+
66#	    - color
67#		<hex> | transparent
68#	    - align
69#		left | right | center | justify
70#	    - botbar
71#		yes | no
72#	    - format
73#	        raw | cooked | lines | <procedure>
74#	    - multicolumn
75#		<int>
76#
77# Historique
78#   2002/05/08 : pda : d�but de la conception
79#   2002/05/10 : pda : codage de l'analyse et des g�n�rations csv et html
80#   2002/05/11 : pda : codage de la g�n�ration latex
81#   2002/05/12 : pda : mise au point
82#   2003/08/08 : pda : somme des largeurs des colonnes ramen�e � 100 %
83#   2006/12/06 : pda : utilisation de CSS
84#
85
86package require webapp
87package provide arrgen 1.1
88
89namespace eval arrgen {
90    #
91    # Fonctions utilisables � l'ext�rieur du package
92    #
93
94    namespace export parse output debug \
95					latex-string
96
97    #
98    # Liste avec valeurs possible : {errors syntax}
99    #
100
101    variable debuginfos {}
102
103    #
104    # Valeurs par d�faut et m�canisme d'h�ritage
105    #
106
107    variable defaults
108    array set defaults {
109	inherit-defaults-global	{
110				    csv-separator
111				    latex-linewidth latex-bordersep
112				    charsize charfont color align botbar format
113				}
114
115	csv-separator		,
116	latex-linewidth		175
117	latex-bordersep		2.3
118
119	charsize		12
120	charfont		normal
121	color			transparent
122	align			left
123	botbar			0
124	format			::arrgen::output-cooked
125
126	inherit-defaults-pattern { ncols title topbar }
127	inherit-global-pattern	{ charsize charfont color align botbar format }
128
129	ncols			0
130	title			0
131	topbar			0
132
133	vbar			0
134
135	inherit-defaults-column { span }
136	inherit-pattern-column	{ charsize charfont color align botbar format }
137
138	span			1
139
140    }
141
142    #
143    # Caract�res � ignorer en latex
144    #
145
146    variable latex_ignore
147
148    #
149    # Cha�ne de format pour utiliser CSS : classes � utiliser en
150    # fonction de la taille de la fonte.
151    # Si la cha�ne est vide, le format classique ("font size=") est utilis�.
152    #
153
154    variable css_size "tab-text%d"
155}
156
157
158##############################################################################
159# Activation du debug
160##############################################################################
161
162proc ::arrgen::debug {infos} {
163    set ::arrgen::debuginfos $infos
164}
165
166##############################################################################
167# Proc�dure principale du package
168##############################################################################
169
170#
171# Proc�dure principale
172#
173# Entr�e :
174#   - param�tres :
175#       - format : html/latex/csv
176#       - style : le style proprement dit, ou le tableau d�j� analys�
177#	- data : les donn�es
178#   - variables globales :
179#	- debuginfo : les informations de debug souhait�es
180# Sortie :
181#   - valeur de retour : valeur convertie en tableau, ou message d'erreur
182#
183# Note : voir la sp�cification du style dans l'en-t�te du package
184#
185# Historique :
186#   2002/05/10 : pda : conception
187#
188
189proc ::arrgen::output {format style data} {
190    global errorInfo
191
192    if {[llength $style] == 1} then {
193	upvar $style tab
194    } else {
195	if {[::arrgen::parse tab $style msg] == -1} then {
196	    puts stderr "Error: $msg"
197	    return $msg
198	}
199    }
200
201    set rp [catch {::arrgen::output-format $format tab $data} m]
202    set savedinfo $errorInfo
203
204    if {[lsearch $::arrgen::debuginfos errors] != -1 && $rp != 0} then {
205	set m $savedinfo
206    }
207    return $m
208}
209
210proc ::arrgen::output-format {format tab data} {
211    upvar $tab t
212
213    #
214    # Caract�res � ignorer en format latex
215    #
216    set ::arrgen::latex_ignore ""
217    foreach {min max} {0 8    11 31    127 160} {
218	for {set i $min} {$i <= $max} {incr i} {
219	    append ::arrgen::latex_ignore [format %c $i]
220	}
221    }
222
223    #
224    # Obtention du format de sortie
225    #
226    set kwd [::arrgen::get-kwd $format "format" \
227			{ {html html} {latex latex} {pdf latex} {csv csv} } ]
228
229    #
230    # G�n�ration et renvoi du r�sultat
231    #
232    return [::arrgen::output-$kwd t $data]
233}
234
235##############################################################################
236# Analyse syntaxique du style
237##############################################################################
238
239#
240# Analyse syntaxique du style
241#
242# Entr�e :
243#   - param�tres :
244#       - tab : tableau � remplir, contenant le style en retour
245#       - style : le style proprement dit
246#	- msg : message d'erreur en retour
247# Sortie :
248#   - valeur de retour : 0 si tout s'est bien pass�, ou -1 en cas d'erreur
249#   - param�tre tableau : le tableau rempli
250#   - param�tre msg : le message d'erreur en cas d'erreur
251#
252# Note : voir la sp�cification du style dans l'en-t�te du package
253#
254# Historique :
255#   2002/05/10 : pda : conception
256#
257
258proc ::arrgen::parse {tab style msg} {
259    upvar $tab t
260    upvar $msg m
261    global ::arrgen::debuginfos
262    global errorInfo
263
264    catch {unset t}
265    set r 0
266    set rp [catch {::arrgen::parse-style t $style} m]
267    set savedinfo $errorInfo
268
269    if {[lsearch $::arrgen::debuginfos syntax] != -1} then {
270	foreach f [lsort [array names t]] {
271	    puts stderr [format "| %-40s | %-30s |" $f $t($f)]
272	}
273    }
274
275    if {[lsearch $::arrgen::debuginfos errors] != -1 && $rp != 0} then {
276	set m $savedinfo
277    }
278
279    if {$rp != 0} then {
280	set r -1
281    } else {
282	set r 0
283    }
284    return $r
285}
286
287#
288# Proc�dures d'analyse des �l�ments du style
289#
290# Entr�e :
291#   - param�tres :
292#       - tab : tableau en cours de remplissage
293#       - style : la partie du style � analyser
294#	- msg : message d'erreur en retour
295# Sortie :
296#   - valeur de retour : aucune
297#   - erreur : s'il y a eu erreur
298#   - param�tre tab : le tableau en cours de remplissage
299#
300# Historique :
301#   2002/05/10 : pda : conception
302#
303
304proc ::arrgen::parse-style {tab style} {
305    upvar $tab t
306
307    while {[llength $style] > 0} {
308	set kwd [lindex $style 0]
309	set arg [lindex $style 1]
310	set n 1
311
312	set kwd [::arrgen::get-kwd $kwd "top" \
313			{
314			    {global global}	{global global}
315			    {pattern pattern}	{motif pattern}
316			} ]
317
318	switch -- $kwd {
319	    global {
320		::arrgen::parse-global t $arg
321	    }
322	    pattern {
323		::arrgen::parse-pattern t [lindex $style 2] $arg
324		set n 2
325	    }
326	}
327	set style [lreplace $style 0 $n]
328    }
329}
330
331########################################
332# Global
333########################################
334
335proc ::arrgen::parse-global {tab style} {
336    upvar $tab t
337
338    #
339    # Valeurs par d�faut
340    #
341    ::arrgen::inherit ::arrgen::defaults "" t "" \
342			$::arrgen::defaults(inherit-defaults-global)
343
344    #
345    # Analyse de la liste
346    #
347    set ctxt "global"
348
349    while {[llength $style] > 0} {
350	set kwd [lindex $style 0]
351	set arg [lindex $style 1]
352
353	set kwd [::arrgen::get-kwd $kwd $ctxt \
354			{
355			    {chars chars}	{caracteres chars}
356			    {color color}	{couleur color}
357			    {align align}	{alignement align}
358			    {botbar botbar}	{trait-horizontal botbar}
359			    {format format}	{donnees-formatees format}
360			    {columns columns}	{colonnes columns}
361			    {csv   csv}
362			    {latex latex}
363			} ]
364
365	::arrgen::parse-$kwd t $arg "" $ctxt
366	set style [lreplace $style 0 1]
367    }
368}
369
370#
371# Remplit :
372#   (rien)
373#
374
375proc ::arrgen::parse-ignore {tab style idx ctxt} {
376}
377
378#
379# Remplit :
380#   tab(charsize) :				<taille des caract�res>
381#   tab(charfont) :				normal|bold|bold-italic|italic
382# ou :
383#   tab(pattern-PPP-charsize) :			<taille des caract�res>
384#   tab(pattern-PPP-charfont) :			normal|bold|bold-italic|italic
385# ou :
386#   tab(pattern-PPP-col-CCC-charsize) :		<taille des caract�res>
387#   tab(pattern-PPP-col-CCC-charfont) :		normal|bold|bold-italic|italic
388#
389
390proc ::arrgen::parse-chars {tab style idx ctxt} {
391    upvar $tab t
392
393    set x(normal)	0
394    set x(bold)		0
395    set x(italic)	0
396
397    foreach s $style {
398	set kwd [::arrgen::get-kwd $s $ctxt \
399			{
400			    {normal normal}	{normal normal}
401			    {bold bold}		{gras bold}
402			    {italic italic}	{italique italic}
403			    {[0-9]+ int}
404			} ]
405
406	if {[string equal $kwd int]} then {
407	    set t(${idx}charsize) $s
408	} else {
409	    set x($kwd) 1
410	}
411    }
412
413    switch -glob -- "$x(normal)$x(bold)$x(italic)" {
414	000 { }
415	001 { set t(${idx}charfont) "italic" }
416	010 { set t(${idx}charfont) "bold" }
417	011 { set t(${idx}charfont) "bold-italic" }
418	100 { set t(${idx}charfont) "normal" }
419	1*  {
420	    ::arrgen::invalid-keyword "combination normal/bold/italic" \
421				"chars" {normal bold italic}
422	}
423    }
424}
425
426#
427# Remplit
428#   tab(color) :			<color>
429# ou :
430#   tab(pattern-PPP-color) :		<color>
431# ou :
432#   tab(pattern-PPP-col-CCC-color) :	<color>
433#
434
435proc ::arrgen::parse-color {tab style idx ctxt} {
436    upvar $tab t
437
438    set kwd [::arrgen::get-kwd $style $ctxt \
439		    {
440			{transparent transparent}
441			{[0-9A-Fa-f]+ hex}
442		    } ]
443
444    switch -- $kwd {
445	transparent {
446	    set t(${idx}color) $style
447	}
448	hex {
449	    set t(${idx}color) [string toupper $style]
450	}
451    }
452}
453
454#
455# Remplit :
456#   tab(align)				<left/center/right/justify>
457# ou :
458#   tab(pattern-PPP-align)		<left/center/right/justify>
459# ou :
460#   tab(pattern-PPP-col-CCC-align)	<left/center/right/justify>
461#
462
463proc ::arrgen::parse-align {tab style idx ctxt} {
464    upvar $tab t
465
466    set t(${idx}align) [::arrgen::get-kwd $style "$ctxt, align" \
467			    {
468				{left left}	{gauche left}
469				{center center}	{centre center}
470				{right right}	{droit right}
471				{justify justify}
472			    } ]
473}
474
475#
476# Remplit :
477#   tab(botbar)				<0/1>
478# ou :
479#   tab(pattern-PPP-botbar)		<0/1>
480# ou :
481#   tab(pattern-PPP-col-CCC-botbar)	<0/1>
482#
483
484proc ::arrgen::parse-botbar {tab style idx ctxt} {
485    upvar $tab t
486
487    set t(${idx}botbar) [::arrgen::get-yesno $style "$ctxt, botbar"]
488}
489
490
491#
492# Remplit :
493#   tab(ncols) :		<nb de columns>
494#   tab(col-CCC-width) :	<largeur de la colonne CCC en %>
495#
496
497proc ::arrgen::parse-columns {tab style idx ctxt} {
498    upvar $tab t
499
500    set ncols 0
501    set total 0
502    foreach c $style {
503	incr ncols
504	set t(col-$ncols-width) [::arrgen::get-int $c "global, column $ncols size"]
505	incr total $c
506    }
507
508    set t(ncols) $ncols
509
510    #
511    # Ancienne version : test strict d'�galit� � 100 %
512    #
513
514#    if {$total != 100} then {
515#	error "Size of all $ncols columns is '$total', should be 100"
516#    }
517
518    #
519    # Nouvelle version : on ram�ne � 100 %
520    #
521
522    if {$total != 100} then {
523	set ncols 0
524	set ntotal 0
525	foreach c $style {
526	    incr ncols
527	    set w $t(col-$ncols-width)
528	    set nw [expr "round (100.0 * double($w) / $total)"]
529	    set t(col-$ncols-width) $nw
530	    incr ntotal $nw
531	}
532	if {$ntotal != 100} then {
533	    incr t(col-$ncols-width) [expr 100-$ntotal]
534	}
535    }
536}
537
538########################################
539# CSV specific parameters
540########################################
541
542proc ::arrgen::parse-csv {tab style idx ctxt} {
543    upvar $tab t
544
545    while {[llength $style] > 0} {
546	set kwd [lindex $style 0]
547	set arg [lindex $style 1]
548
549	set kwd [::arrgen::get-kwd $kwd $ctxt \
550			{
551			    {separator csv-separator}
552			} ]
553
554	::arrgen::parse-$kwd t $arg "" $ctxt
555	set style [lreplace $style 0 1]
556    }
557}
558
559#
560# Remplit :
561#   tab(csv-separator)		<char>
562#
563
564proc ::arrgen::parse-csv-separator {tab style idx ctxt} {
565    upvar $tab t
566
567    if {[string length $style] != 1} then {
568	error "CSV separator must be exactly one character"
569    }
570
571    set t(${idx}csv-separator) $style
572}
573
574########################################
575# LaTeX specific parameters
576########################################
577
578proc ::arrgen::parse-latex {tab style idx ctxt} {
579    upvar $tab t
580
581    while {[llength $style] > 0} {
582	set kwd [lindex $style 0]
583	set arg [lindex $style 1]
584
585	set kwd [::arrgen::get-kwd $kwd $ctxt \
586			{
587			    {linewidth latex-linewidth}
588			    {bordersep latex-bordersep}
589			} ]
590
591	::arrgen::parse-$kwd t $arg "" $ctxt
592	set style [lreplace $style 0 1]
593    }
594}
595
596#
597# Remplit :
598#   tab(latex-linewidth)	<float>
599#
600
601proc ::arrgen::parse-latex-linewidth {tab style idx ctxt} {
602    upvar $tab t
603
604    set t(${idx}latex-linewidth) [expr double($style)]
605}
606
607#
608# Remplit :
609#   tab(latex-bordersep)	<float>
610#
611
612proc ::arrgen::parse-latex-bordersep {tab style idx ctxt} {
613    upvar $tab t
614
615    set t(${idx}latex-bordersep) [expr double($style)]
616}
617
618########################################
619# Pattern
620########################################
621
622#
623# Remplit :
624#   tab(patterns)		ajoute le nom du motif
625#   tab(pattern-PPP-ncols)	<nb de colonnes du motif PPP>
626#   tab(pattern-PPP-col-CCC-vbar)	<0/1>
627#
628
629proc ::arrgen::parse-pattern {tab style name} {
630    upvar $tab t
631
632    if {! [regexp {^[-A-Za-z0-9]+$} $name]} then {
633	error "Invalid syntax for pattern '$name'"
634    }
635
636    lappend t(patterns) $name
637    set idx "pattern-$name-"
638
639    #
640    # Valeurs par d�faut du motif
641    #
642
643    if {! [info exists t(charsize)]} then {
644	error "Section 'global' not found"
645    }
646
647    ::arrgen::inherit ::arrgen::defaults "" t $idx \
648			$::arrgen::defaults(inherit-defaults-pattern)
649    ::arrgen::inherit t "" t $idx \
650			$::arrgen::defaults(inherit-global-pattern)
651
652    set t(${idx}col-0-vbar)	$::arrgen::defaults(vbar)
653
654    #
655    # Analyse du motif
656    #
657
658    set ctxt "pattern '$name'"
659
660    while {[llength $style] > 0} {
661	set kwd [lindex $style 0]
662	set arg [lindex $style 1]
663
664	set kwd [::arrgen::get-kwd $kwd $ctxt \
665			{
666			    {chars chars}	{caracteres chars}
667			    {color color}	{couleur color}
668			    {align align}	{alignement align}
669			    {botbar botbar}	{trait-horizontal botbar}
670			    {format format}	{donnees-formatees format}
671			    {topbar topbar}	{trait-dessus topbar}
672			    {title title}
673			    {vbar vbar}		{trait-vertical vbar}
674			    {column column}	{colonne column}
675
676			    {repetition ignore}
677			    {afficher ignore}
678			} ]
679
680	::arrgen::parse-$kwd t $arg $idx $ctxt
681
682	set style [lreplace $style 0 1]
683    }
684
685    set lastcol $t(${idx}ncols)
686    for {set c 0} {$c <= $lastcol} {incr c} {
687	if {! [info exists t(${idx}col-$c-vbar)]} then {
688	    set t(${idx}col-$c-vbar) $::arrgen::defaults(vbar)
689	}
690    }
691
692    set ncol 0
693    for {set c 1} {$c <= $lastcol} {incr c} {
694	incr ncol $t(${idx}col-$c-span)
695    }
696
697    if {$ncol != $t(ncols)} then {
698	error "Invalid number of columns ($ncol) in pattern '$name'"
699    }
700}
701
702#
703# Remplit :
704#   tab(pattern-PPP-topbar)		<0/1>
705#
706
707proc ::arrgen::parse-topbar {tab style idx ctxt} {
708    upvar $tab t
709
710    set t(${idx}topbar) [::arrgen::get-yesno $style "$ctxt, topbar"]
711}
712
713
714#
715# Remplit :
716#   tab(pattern-PPP-title)		<0/1>
717#
718
719proc ::arrgen::parse-title {tab style idx ctxt} {
720    upvar $tab t
721
722    set t(${idx}title) [::arrgen::get-yesno [lindex $style 0] $ctxt]
723}
724
725#
726# Remplit :
727#   tab(pattern-PPP-col-CCC-vbar)	<0/1>
728#
729
730proc ::arrgen::parse-vbar {tab style idx ctxt} {
731    upvar $tab t
732
733    set colnum $t(${idx}ncols)
734    set t(${idx}col-$colnum-vbar) [::arrgen::get-yesno $style "$ctxt, vbar"]
735}
736
737########################################
738# Column
739########################################
740
741#
742# idx = pattern-PPP
743#
744# Remplit :
745#   tab(pattern-PPP-ncols)		<nb de colonnes du motif PPP>
746#
747
748proc ::arrgen::parse-column {tab style idx ctxt} {
749    upvar $tab t
750
751    incr t(${idx}ncols)
752    set colnum $t(${idx}ncols)
753    set colidx ${idx}col-$colnum-
754
755    append ctxt ", column $colnum"
756
757    #
758    # Valeurs par d�faut de la colonne
759    #
760
761    ::arrgen::inherit ::arrgen::defaults "" t $colidx \
762			$::arrgen::defaults(inherit-defaults-column)
763    ::arrgen::inherit t $idx t $colidx \
764			$::arrgen::defaults(inherit-pattern-column)
765
766    #
767    # Analyse des arguments
768    #
769
770    while {[llength $style] > 0} {
771	set kwd [lindex $style 0]
772	set arg [lindex $style 1]
773
774	set kwd [::arrgen::get-kwd $kwd $ctxt \
775			{
776			    {chars chars}	{caracteres chars}
777			    {color color}	{couleur color}
778			    {align align}	{alignement align}
779			    {botbar botbar}	{trait-horizontal botbar}
780			    {multicolumn multicolumn}	{multi-colonnes multicolumn}
781			    {multicolumns multicolumn}
782			    {format format}	{donnees-formatees format}
783			} ]
784
785	::arrgen::parse-$kwd t $arg $colidx $ctxt
786	set style [lreplace $style 0 1]
787    }
788}
789
790#
791# Remplit :
792#   tab(pattern-PPP-col-CCC-span)	<int>
793#
794
795proc ::arrgen::parse-multicolumn {tab style idx ctxt} {
796    upvar $tab t
797
798    set t(${idx}span) [::arrgen::get-int $style "$ctxt, multicolumn"]
799}
800
801#
802# Remplit :
803#   tab(pattern-PPP-col-CCC-format)	<nom de proc�dure>
804#			(avec deux proc�dures pr�cod�es : raw et cooked)
805#
806
807proc ::arrgen::parse-format {tab style idx ctxt} {
808    upvar $tab t
809
810    set kwd [::arrgen::get-kwd $style "$ctxt, align" \
811			    {
812				{cooked cooked}
813				{raw    raw}
814				{lines  lines}
815				{oui    raw}  	{non cooked}
816				{[-a-zA-Z0-9]+ proc}
817			    } ]
818    switch $kwd {
819	proc    { set v [list proc $style] }
820	default { set v "::arrgen::output-$kwd" }
821    }
822    set t(${idx}format) $v
823}
824
825########################################
826# Utilitaires
827########################################
828
829proc ::arrgen::get-yesno {val ctxt} {
830    return [::arrgen::get-kwd $val $ctxt \
831		    {
832			{oui 1} {yes 1} {1 1} {non 0} {no 0} {0 0}
833		    } ]
834}
835
836proc ::arrgen::get-kwd {val ctxt lval} {
837    set ak {}
838    foreach v $lval {
839	set re [lindex $v 0]
840	lappend ak $re
841	if {[regexp "^$re$" $val]} then {
842	    return [lindex $v 1]
843	}
844    }
845    ::arrgen::invalid-keyword $val $ctxt $ak
846}
847
848proc ::arrgen::get-int {val ctxt} {
849    if {! [regexp {^[0-9]+} $val]} then {
850	error "Invalid integer '$val' in context '$ctxt'"
851    }
852    return $val
853}
854
855proc ::arrgen::invalid-keyword {kwd ctxt defval} {
856    set shouldbe ""
857    if {[llength $defval] > 0} then {
858	set defval [join $defval "|"]
859	set shouldbe " : should be $defval"
860    }
861    error "Invalid keyword '$kwd' in context '$ctxt'$shouldbe"
862}
863
864proc ::arrgen::inherit {tabtop topctxt tabcur curctxt fields} {
865    upvar $tabtop ttop
866    upvar $tabcur tcur
867
868    foreach f $fields {
869	if {[info exists ttop($topctxt$f)]} then {
870	    set tcur($curctxt$f) $ttop($topctxt$f)
871	} else {
872	    error "Internal : bad inherit field '$topctxt$f' -> '$curctxt$f'"
873	}
874    }
875}
876
877##############################################################################
878# Fonctions auxiliaires de g�n�ration
879##############################################################################
880
881#
882# Effectue quelques v�rifications �l�mentaires sur la ligne du tableau
883#
884# Entr�e :
885#   - param�tres :
886#       - tab : le tableau contenant le style
887#	- lineno : num�ro de la ligne courante
888#	- line : la ligne courante (y compris le motif)
889# Sortie :
890#   - valeur de retour : -
891#
892# Historique :
893#   2002/05/10 : pda : conception
894#
895
896proc ::arrgen::check-pattern-nbcols {tab lineno line} {
897    upvar $tab t
898
899    set pattern [lindex $line 0]
900
901    if {[lsearch -exact $t(patterns) $pattern] == -1} then {
902	error "Line $lineno: pattern '$pattern' not found"
903    }
904
905    set ncols [expr [llength $line] - 1]
906    if {$ncols != $t(pattern-$pattern-ncols)} then {
907	error "Line $lineno: invalid nb of columns ($ncols) for pattern '$pattern'"
908    }
909}
910
911#
912# Indique s'il faut une bordure au tableau
913#
914# Entr�e :
915#   - param�tres :
916#       - tab : tableau contenant le style
917# Sortie :
918#   - valeur de retour : 0 ou 1
919#
920# Note : HTML ne disposant pas de moyen pour d�finir la bordure de chaque
921#   case, on d�finit, par convention, que s'il y a au moins un trait
922#   ext�rieur vertical (trait avant la case la plus � gauche, ou apr�s la
923#   case la plus � droite), on met une bordure.
924#
925# Historique :
926#   2002/05/11 : pda : conception
927#   2002/05/14 : pda : conception
928#
929
930proc ::arrgen::any-vbar {tab} {
931    upvar $tab t
932
933    set r 0
934    foreach p $t(patterns) {
935	set idx "pattern-$p-"
936	set ncols $t(${idx}ncols)
937	if {$t(${idx}col-0-vbar) || $t(${idx}col-$ncols-vbar)} then {
938	    set r 1
939	    break
940	}
941    }
942    return $r
943}
944
945##############################################################################
946# G�n�ration csv
947##############################################################################
948
949#
950# G�n�ration du tableau en format CSV
951#
952# Entr�e :
953#   - param�tres :
954#       - tab : tableau contenant le style
955#	- data : les donn�es
956# Sortie :
957#   - valeur de retour : valeur convertie en tableau
958#
959# Historique :
960#   2002/05/10 : pda : conception
961#
962
963proc ::arrgen::output-csv {tab data} {
964    upvar $tab t
965
966    set lineno 0
967    set csv ""
968    foreach line $data {
969	incr lineno
970	::arrgen::check-pattern-nbcols t $lineno $line
971	set idx "pattern-[lindex $line 0]-"
972	append csv [::arrgen::output-csv-line t $idx [lreplace $line 0 0]]
973    }
974    return $csv
975}
976
977#
978# G�n�ration d'une ligne CSV du tableau
979#
980# Entr�e :
981#   - param�tres :
982#       - tab : tableau contenant le style
983#	- idx : index du motif dans le tableau tab
984#	- line : la ligne compos�e d'une liste des colonnes
985# Sortie :
986#   - valeur de retour : ligne convertie en ligne de tableau
987#
988# Historique :
989#   2002/05/10 : pda : conception
990#
991
992proc ::arrgen::output-csv-line {tab idx line} {
993    upvar $tab t
994
995    set csvlist {}
996    set icol 0
997    foreach val $line {
998	incr icol
999
1000	set needquote 0
1001	if {[regsub -all {"} $val {""} csvval] > 0} then {
1002	    set needquote 1
1003	}
1004	if {[regexp $t(csv-separator) $csvval]} then {
1005	    set needquote 1
1006	}
1007	if {[regexp {[\n\r]} $csvval]} then {
1008	    set needquote 1
1009	}
1010	if {$needquote} then {
1011	    set csvval "\"$csvval\""
1012	}
1013
1014	lappend csvlist $csvval
1015
1016	for {set i 2} {$i < $t(${idx}col-$icol-span)} {incr i} {
1017	    lappend csvlist {}
1018	}
1019    }
1020    append csv "[join $csvlist $t(csv-separator)]\n"
1021}
1022
1023##############################################################################
1024# G�n�ration html
1025##############################################################################
1026
1027#
1028# G�n�ration du tableau en format HTML
1029#
1030# Entr�e :
1031#   - param�tres :
1032#       - tab : tableau contenant le style
1033#	- data : les donn�es
1034# Sortie :
1035#   - valeur de retour : valeur convertie en tableau
1036#
1037# Historique :
1038#   2002/05/10 : pda : conception
1039#
1040
1041proc ::arrgen::output-html {tab data} {
1042    upvar $tab t
1043
1044    if {[::arrgen::any-vbar t]} then {
1045	set border " BORDER=2 CELLPADDING=5 CELLSPACING=1"
1046    } else {
1047	set border ""
1048    }
1049    set html "<table width=\"100%\"$border>\n"
1050
1051    set lineno 0
1052    foreach line $data {
1053	incr lineno
1054	::arrgen::check-pattern-nbcols t $lineno $line
1055	set idx "pattern-[lindex $line 0]-"
1056	append html [::arrgen::output-html-line t $idx [lreplace $line 0 0]]
1057    }
1058
1059    append html "</table>\n"
1060
1061    return $html
1062}
1063
1064#
1065# G�n�ration d'une ligne HTML du tableau
1066#
1067# Entr�e :
1068#   - param�tres :
1069#       - tab : tableau contenant le style
1070#	- idx : index du motif dans le tableau tab
1071#	- line : la ligne compos�e d'une liste des colonnes
1072# Sortie :
1073#   - valeur de retour : ligne convertie en ligne de tableau
1074#
1075# Historique :
1076#   2002/05/10 : pda : conception
1077#   2002/05/18 : pda : ajout du param�tre align -> jusitfy
1078#
1079
1080proc ::arrgen::output-html-line {tab idx line} {
1081    upvar $tab t
1082
1083    set html ""
1084    set icol 0
1085    set realcol 0
1086    foreach val $line {
1087	incr icol
1088	incr realcol
1089
1090	set colidx "${idx}col-$icol-"
1091
1092	# Alignement et justification
1093	switch $t(${colidx}align) {
1094	    left	{ set align " align=left" }
1095	    center	{ set align " align=center" }
1096	    right	{ set align " align=right" }
1097	    justify	{ set align "" }
1098	}
1099
1100	# Multi-colonnes
1101	set span $t(${colidx}span)
1102	set width $t(col-$realcol-width)
1103	for {set i 1} {$i < $span} {incr i} {
1104	    incr realcol
1105	    incr width $t(col-$realcol-width)
1106	}
1107	if {$span > 1} then {
1108	    set colspan " colspan=\"$span\""
1109	} else {
1110	    set colspan ""
1111	}
1112
1113	# Largeur
1114	set width " width=\"$width%\""
1115
1116	# Couleur
1117	if {[string equal $t(${colidx}color) "transparent"]} then {
1118	    set color ""
1119	} else {
1120	    set color " bgcolor=\"#$t(${colidx}color)\""
1121	}
1122
1123	# taille
1124	set class ""
1125	if {! [string equal $::arrgen::css_size ""]} then {
1126	    set css [format $::arrgen::css_size  $t(${colidx}charsize)]
1127	    set class [format " class=\"$css\""]
1128	}
1129
1130
1131	# D�but de la colonne
1132	append html "<td$width$colspan$align$color$class>"
1133
1134	set font [::arrgen::html-font $t(${colidx}charsize) $t(${colidx}charfont)]
1135	append html "[lindex $font 0]\n"
1136
1137	if {[string length [string trim $val]] == 0} then {
1138	    set val "&nbsp;"
1139	} else {
1140	    set fmt $t(${colidx}format)
1141	    set val [$fmt html $t(${colidx}align) $val]
1142	}
1143
1144	append html "$val\n"
1145
1146	# Fin de la colonne
1147	append html "[lindex $font 1]\n"
1148	append html "</td>\n"
1149    }
1150    return "<tr>\n$html</tr>\n"
1151}
1152
1153#
1154# Correspondance entre les sp�cifications de police et le code html
1155#
1156# Entr�e :
1157#   - param�tres :
1158#       - size : taille de police telle qu'elle figure dans le style
1159#       - font : police telle qu'elle figure dans le style
1160# Sortie :
1161#   - valeur de retour : liste � deux �l�ments {a b} o� "a" est le
1162#	code � ins�rer avant le texte, et "b" le code � ins�rer apr�s.
1163#
1164# Historique :
1165#   2002/05/10 : pda : conception
1166#   2006/12/06 : pda : support css
1167#
1168
1169proc ::arrgen::html-font {size font} {
1170    #
1171    # Taille de la fonte
1172    #
1173
1174    if {[string equal $::arrgen::css_size ""]} then {
1175	if {$size <= 8} then {
1176	    set s "1"
1177	} elseif {$size <= 10} then {
1178	    set s "2"
1179	} elseif {$size <= 12} then {
1180	    set s "3"
1181	} elseif {$size <= 14} then {
1182	    set s "4"
1183	} elseif {$size <= 16} then {
1184	    set s "5"
1185	} elseif {$size <= 18} then {
1186	    set s "6"
1187	} elseif {$size <= 20} then {
1188	    set s "7"
1189	} elseif {$size <= 22} then {
1190	    set s "8"
1191	} else {
1192	    set s "9"
1193	}
1194	set size1 "<font size=\"$s\">"
1195	set size2 "</font>"
1196    } else {
1197	set size1 ""
1198	set size2 ""
1199    }
1200
1201    #
1202    # Style
1203    #
1204
1205    switch $font {
1206	normal      { set style1 "" ;       set style2 "" }
1207	bold        { set style1 "<b>" ;    set style2 "</b>" }
1208	italic      { set style1 "<i>" ;    set style2 "</i>" }
1209	bold-italic { set style1 "<b><i>" ; set style2 "</i></b>" }
1210    }
1211
1212    return [list "$size1$style1" "$style2$size2"]
1213}
1214
1215##############################################################################
1216# G�n�ration latex
1217##############################################################################
1218
1219#
1220# G�n�ration du tableau en format LATEX
1221#
1222# Entr�e :
1223#   - param�tres :
1224#       - tab : tableau contenant le style
1225#	- data : les donn�es
1226# Sortie :
1227#   - valeur de retour : valeur convertie en tableau
1228#
1229# Historique :
1230#   2002/05/10 : pda : conception
1231#
1232
1233proc ::arrgen::output-latex {tab data} {
1234    upvar $tab t
1235
1236    ::arrgen::latex-colwidth t
1237    ::arrgen::latex-botbar t
1238
1239    set latex ""
1240
1241    #
1242    # Faut-il des bordures horizontales en haut et en bas de
1243    # chaque page du tableau ?
1244    #
1245
1246    set title ""
1247    if {[::arrgen::any-vbar t]} then {
1248	append latex "\\tabletail \{\\hline\}\n"
1249	append latex "\\tablehead \{\\hline\}\n"
1250    } else {
1251	append latex "\\tabletail \{\}\n"
1252	append latex "\\tablehead \{\}\n"
1253    }
1254    append latex "\\tablefirsthead \{\}\n"
1255    append latex "\\tablelasttail \{\}\n"
1256
1257    #
1258    # Pr�paration de l'en-t�te, qu'on ne sortira qu'� la premi�re
1259    # ligne affichable.
1260    #
1261    set cols [string repeat "c" $t(ncols)]
1262    set header "\\begin \{supertabular\} \{$cols\}\n"
1263    set headerprinted 0
1264
1265    set lineno 0
1266    set nlines [llength $data]
1267    foreach line $data {
1268	incr lineno
1269	::arrgen::check-pattern-nbcols t $lineno $line
1270	set idx "pattern-[lindex $line 0]-"
1271
1272	set l [::arrgen::output-latex-line t $idx [lreplace $line 0 0]]
1273
1274	#
1275	# Est-ce que cette ligne est une ligne sp�ciale (i.e. � r�p�ter) ?
1276	#
1277
1278	if {$t(${idx}title)} then {
1279	    append title $l
1280	    append latex "\\tablefirsthead \{$title\}"
1281	    append latex "\\tablehead \{$title\}"
1282	} else {
1283	    if {! $headerprinted} then {
1284		append latex $header
1285		set headerprinted 1
1286	    }
1287	    append latex $l
1288	}
1289    }
1290
1291    if {$headerprinted} then {
1292	append latex "\\end \{supertabular\}\n"
1293    }
1294
1295    return $latex
1296}
1297
1298#
1299# Calcul des tailles de toutes les colonnes possibles du tableau.
1300#
1301# Entr�e :
1302#   - param�tres :
1303#       - tab : tableau contenant le style
1304# Sortie :
1305#   - valeur de retour : -
1306#   - param�tre tab :
1307#	t(pattern-PPP-col-CCC-latexwidth) : taille � mettre avec \linewidth
1308#
1309# Note :
1310#    Le texte dans une cellule de tableau latex est bord� par
1311#    un petit espace E de part et d'autre. Cet espace E = 2,3 mm.
1312#
1313#                   60 %                           40 %
1314#    | <------------------------------> | <--------------------> |
1315#    |                                  |                        |
1316#    |   E           T1             E       E      T2        E   |
1317#    | <--> <--------------------> <--> | <--> <----------> <--> |
1318#    |                                                           |
1319#    |   E          T12 (multicolonne sur 1 et 2)            E   |
1320#    | <--> <---------------------------------------------> <--> |
1321#
1322#    Toutes les dimensions doivent �tre proportionnelles �
1323#    \linewidth. Seul E (2,3 mm) ne peut �tre d�riv� de \linewidth
1324#    exactement. C'est pour cela qu'on prend une approximation :
1325#    si \linewidth = 175 mm, E = I \linewidth, avec I = 2.3/175
1326#
1327#    Donc, la largeur du texte T dans une colonne C est calcul�e
1328#    empiriquement � partir de :
1329#   	- L = largeur de toutes les colonnes constituant C
1330#   		(notamment en cas de multicolonnage)
1331#   		Exemple L1 = 60%, L2 = 40%, L12 = 100%
1332#   	- B = largeur de la bordure = 2 I
1333#    d'o� T = (L/100 - B) * \linewidth
1334#
1335# Historique :
1336#   2002/05/12 : pda : conception
1337#   2002/05/18 : pda : ajout du param�tre align -> jusitfy
1338#
1339
1340proc ::arrgen::latex-colwidth {tab} {
1341    upvar $tab t
1342
1343    set B [expr 2 * ($t(latex-bordersep) / $t(latex-linewidth))]
1344
1345    foreach p $t(patterns) {
1346	set ncols $t(pattern-$p-ncols)
1347	set realcol 1
1348	set mcol 1
1349	for {set mcol 1} {$mcol <= $ncols} {incr mcol} {
1350	    set span $t(pattern-$p-col-$mcol-span)
1351	    set L 0
1352	    for {set i 0} {$i < $span} {incr i} {
1353		incr L $t(col-$realcol-width)
1354		incr realcol
1355	    }
1356	    set t(pattern-$p-col-$mcol-latexwidth) [expr ($L / 100.0) - $B]
1357	}
1358    }
1359}
1360
1361#
1362# Calcul de tous les traits en dessous des colonnes
1363#
1364# Entr�e :
1365#   - param�tres :
1366#       - tab : tableau contenant le style
1367# Sortie :
1368#   - valeur de retour : -
1369#   - param�tre tab :
1370#	t(pattern-PPP-latexbotbar) : {{min max} {max max} ...}
1371#		avec min et max les param�tres pour \cline
1372#		et min = -1 si \hline
1373#
1374# Historique :
1375#   2002/05/12 : pda : conception
1376#   2002/05/25 : pda : correction d'un bug si max = realcol - 1
1377#
1378
1379proc ::arrgen::latex-botbar {tab} {
1380    upvar $tab t
1381
1382    foreach p $t(patterns) {
1383	set botidx pattern-$p-latexbotbar
1384	set t($botidx) {}
1385
1386	set begin -1
1387	set realcol 1
1388	set ncols $t(pattern-$p-ncols)
1389
1390	for {set mcol 1} {$mcol <= $ncols} {incr mcol} {
1391	    set lastrealcol [expr $realcol - 1]
1392
1393	    if {$t(pattern-$p-col-$mcol-botbar)} then {
1394		# une barre en dessous de la colonne
1395		if {$begin <= 0} then {
1396		    # d�but d'un cline
1397		    set begin $realcol
1398		}
1399	    } else {
1400		# pas de barre en dessous de la colonne
1401		if {$begin > 0} then {
1402		    lappend t($botidx) [list $begin $lastrealcol]
1403		    set begin -1
1404		}
1405	    }
1406	    incr realcol $t(pattern-$p-col-$mcol-span)
1407	}
1408
1409	if {$begin == 1} then {
1410	    lappend t($botidx) {-1 -1}
1411	} elseif {$begin > 1} then {
1412	    lappend t($botidx) [list $begin [expr $realcol - 1]]
1413	}
1414    }
1415}
1416
1417#
1418# G�n�ration d'une ligne LATEX du tableau
1419#
1420# Entr�e :
1421#   - param�tres :
1422#       - tab : tableau contenant le style
1423#	- idx : index du motif dans le tableau tab
1424#	- line : la ligne compos�e d'une liste des colonnes
1425# Sortie :
1426#   - valeur de retour : ligne convertie en ligne de tableau
1427#
1428# Historique :
1429#   2002/05/10 : pda : conception
1430#
1431
1432proc ::arrgen::output-latex-line {tab idx line} {
1433    upvar $tab t
1434
1435    set latex ""
1436
1437    #
1438    # Le trait au dessus n'est en principe que pour la premi�re
1439    # ligne, ou alors pour la premi�re ligne qui suivrait d'autres
1440    # lignes sans trait dessous.
1441    #
1442    if {$t(${idx}topbar)} then {
1443	append latex "\\hline\n"
1444    }
1445
1446    #
1447    # Parcours des cellules de la ligne
1448    #
1449
1450    set icol 0
1451    foreach val $line {
1452	set prevcol $icol
1453	incr icol
1454	set colidx "${idx}col-$icol-"
1455
1456	#
1457	# S�parateur de colonnes
1458	#
1459	if {$icol > 1} then {
1460	    append latex " & "
1461	}
1462
1463	#
1464	# Alignement de la cellule
1465	#
1466	set align $t(${colidx}align)
1467	switch $align {
1468	    left    { set aligncmd "\\raggedright " }
1469	    center  { set aligncmd "\\centering " }
1470	    right   { set aligncmd "\\raggedleft " }
1471	    justify { set aligncmd "" }
1472	}
1473
1474	#
1475	# Traits verticaux de chaque cot� de la cellule
1476	#
1477	set colbefore ""
1478	if {$t(${idx}col-$prevcol-vbar)} then {
1479	    set colbefore "|"
1480	}
1481	set colafter ""
1482	if {$t(${idx}col-$icol-vbar)} then {
1483	    set colafter "|"
1484	}
1485
1486	#
1487	# D�but de la colonne
1488	#
1489	set width $t(${colidx}latexwidth)
1490	set span  $t(${colidx}span)
1491	append latex "\\multicolumn \{$span\}"
1492	append latex " \{${colbefore}p\{$width\\linewidth\}${colafter}\}"
1493	append latex " \{"
1494
1495	#
1496	# Police
1497	#
1498	set font [::arrgen::latex-font $t(${colidx}charsize) $t(${colidx}charfont)]
1499	append latex [lindex $font 0]
1500	append latex $aligncmd
1501
1502	#
1503	# Le texte
1504	#
1505	set fmt $t(${colidx}format)
1506	append latex [$fmt latex $align $val]
1507
1508	#
1509	# Fin de la colonne
1510	#
1511	append latex [lindex $font 1]
1512	append latex "\}\n"
1513    }
1514
1515    #
1516    # Fin de la ligne
1517    #
1518
1519    append latex "\\tabularnewline"
1520
1521    #
1522    # Recherche des traits horizontaux � mettre :
1523    # - soit une s�rie de cline
1524    # - soit un seul hline
1525    #
1526
1527    foreach botbar $t(${idx}latexbotbar) {
1528	set first [lindex $botbar 0]
1529	set last  [lindex $botbar 1]
1530
1531	if {$first == -1} then {
1532	    append latex " \\hline"
1533	} else {
1534	    append latex " \\cline \{$first-$last\}"
1535	}
1536    }
1537
1538    return "$latex\n"
1539}
1540
1541#
1542# Correspondance entre les sp�cifications de police et le code latex
1543#
1544# Entr�e :
1545#   - param�tres :
1546#       - size : taille de police telle qu'elle figure dans le style
1547#       - font : police telle qu'elle figure dans le style
1548# Sortie :
1549#   - valeur de retour : liste � deux �l�ments {a b} o� "a" est le
1550#	code � ins�rer avant le texte, et "b" le code � ins�rer apr�s.
1551#
1552# Historique :
1553#   2002/05/10 : pda : conception
1554#
1555
1556proc ::arrgen::latex-font {size font} {
1557    #
1558    # Taille de la fonte
1559    #
1560
1561    if {$size <= 8} then {
1562	set s "\\scriptsize"
1563    } elseif {$size <= 10} then {
1564	set s "\\footnotesize"
1565    } elseif {$size <= 12} then {
1566	set s "\\normalsize"
1567    } elseif {$size <= 14} then {
1568	set s "\\large"
1569    } elseif {$size <= 16} then {
1570	set s "\\Large"
1571    } elseif {$size <= 20} then {
1572	set s "\\LARGE"
1573    } else {
1574	set s "\\huge"
1575    }
1576
1577    #
1578    # Style. On n'a pas vraiment besoin de style2, mais on
1579    # laisse par souci d'homog�n��t� avec la version html.
1580    #
1581
1582    set it "\\itshape"
1583    set bf "\\bfseries"
1584    switch $font {
1585	normal      { set style1 "" ;        set style2 "" }
1586	bold        { set style1 "$bf " ;    set style2 "" }
1587	italic      { set style1 "$it " ;    set style2 "" }
1588	bold-italic { set style1 "$bf$it " ; set style2 "" }
1589    }
1590
1591    return [list "$s $style1" "$style2"]
1592}
1593
1594#
1595# D�barasse un texte de tous les caract�res sp�ciaux de latex
1596#
1597# Entr�e :
1598#   - param�tres :
1599#       - s : cha�ne � traiter
1600#   - variable globale ::arrgen::latex_ignore
1601#	suite de caract�res � ignorer
1602# Sortie :
1603#   - valeur de retour : la cha�ne trait�e
1604#
1605# Historique :
1606#   2002/05/11 : pda : conception
1607#
1608
1609proc ::arrgen::latex-string {s} {
1610
1611    set patterns {
1612	\\\\		SENTINELLE1
1613
1614	[_&%#\{\}]	\\\\&
1615	\\~		{\\~\ }
1616	\\^		{\\^\ }
1617	\\$		\\\\$
1618	[��]		$^\\circ$
1619			<<
1620			>>
1621			\\EUR\{\}
1622	\\?`		{? `}
1623	!`		{! `}
1624
1625	SENTINELLE1	$\\backslash$
1626    }
1627    regsub -all -- SENTINELLE1 $patterns [format %c 1] patterns
1628
1629    foreach {re sub} $patterns {
1630	regsub -all -- $re $s $sub s
1631    }
1632
1633    regsub -all -- "\[$::arrgen::latex_ignore\]" $s "" s
1634
1635    return $s
1636}
1637
1638
1639##############################################################################
1640# Proc�dures de formattage sp�cialis�es
1641##############################################################################
1642
1643#
1644# Proc�dure de formattage pour le format "raw" : aucune transformation.
1645# Utilis�e pour mettre dans un tableau des URL ou du code sp�cifique.
1646#
1647# Entr�e :
1648#   - param�tres :
1649#       - format  : l'un des formats de sortie (csv, html, latex)
1650#       - align  : l'un des alignements (left, center, right, justify)
1651#	- val : la case de tableau � formatter
1652# Sortie :
1653#   - valeur de retour : la case de tableau convertie au format
1654#
1655# Historique :
1656#   2002/05/10 : pda : conception
1657#   2002/05/18 : pda : ajout du param�tre align
1658#
1659
1660proc ::arrgen::output-raw {format align val} {
1661    return $val
1662}
1663
1664#
1665# Proc�dure de formattage pour le format "cooked" : tous les
1666# caract�res sp�ciaux sont substitu�s le cas �ch�ant.
1667# Utilis�e pour mettre dans un tableau du texte qui doit �tre
1668# formatt� en un seul paragraphe.
1669#
1670# Entr�e :
1671#   - param�tres :
1672#       - format  : l'un des formats de sortie (csv, html, latex)
1673#       - align  : l'un des alignements (left, center, right, justify)
1674#	- val : la case de tableau � formatter
1675# Sortie :
1676#   - valeur de retour : la case de tableau convertie au format
1677#
1678# Historique :
1679#   2002/05/10 : pda : conception
1680#   2002/05/18 : pda : ajout du param�tre align
1681#
1682
1683proc ::arrgen::output-cooked {format align val} {
1684    switch $format {
1685	csv { }
1686	html {
1687	    set val [::webapp::html-string $val]
1688	}
1689	latex {
1690	    set val [::arrgen::latex-string $val]
1691	}
1692    }
1693    return $val
1694}
1695
1696#
1697# Proc�dure de formattage pour le format "lines" : tous les
1698# caract�res sp�ciaux sont substitu�s le cas �ch�ant, et les
1699# sauts de ligne et de paragraphe sont pr�serv�s.
1700#
1701# Entr�e :
1702#   - param�tres :
1703#       - format  : l'un des formats de sortie (csv, html, latex)
1704#       - align  : l'un des alignements (left, center, right, justify)
1705#	- val : la case de tableau � formatter
1706# Sortie :
1707#   - valeur de retour : la case de tableau convertie au format
1708#
1709# Historique :
1710#   2002/05/10 : pda : conception
1711#   2002/05/18 : pda : ajout du param�tre align
1712#
1713
1714proc ::arrgen::output-lines {format align val} {
1715    switch $format {
1716	csv { }
1717	html {
1718	    set val [::webapp::html-string $val]
1719	    regsub -all -- "\n\n+" $val "<p>" val
1720	    if {! [string equal $align "justify"]} then {
1721		regsub -all -- "\n" $val "<br>" val
1722	    }
1723	}
1724	latex {
1725	    set val [::arrgen::latex-string $val]
1726	    regsub -all -- "^(\[ 	\]*\n)+" $val {} val
1727	    regsub -all -- "\n(\[ 	\]*\n)+" $val {\\par } val
1728	    regsub -all -- "\n" $val "\\\\\\\\ \{\}\n" val
1729	}
1730    }
1731    return $val
1732}
1733