1 | |
package org.apache.maven.doxia.module.latex; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
import org.apache.maven.doxia.sink.AbstractTextSink; |
23 | |
import org.apache.maven.doxia.sink.Sink; |
24 | |
import org.apache.maven.doxia.sink.SinkEventAttributes; |
25 | |
import org.apache.maven.doxia.sink.SinkEventAttributeSet; |
26 | |
import org.apache.maven.doxia.util.DoxiaUtils; |
27 | |
import org.apache.maven.doxia.util.LineBreaker; |
28 | |
|
29 | |
import org.codehaus.plexus.util.IOUtil; |
30 | |
import org.codehaus.plexus.util.StringUtils; |
31 | |
|
32 | |
import java.io.IOException; |
33 | |
import java.io.InputStream; |
34 | |
import java.io.Writer; |
35 | |
import java.util.Locale; |
36 | |
|
37 | |
|
38 | |
|
39 | |
|
40 | |
|
41 | |
|
42 | |
|
43 | |
|
44 | |
|
45 | |
public class LatexSink |
46 | |
extends AbstractTextSink |
47 | |
{ |
48 | |
|
49 | |
|
50 | |
|
51 | |
|
52 | |
|
53 | |
private final boolean fragmentDocument; |
54 | |
|
55 | |
private boolean ignoreText; |
56 | |
|
57 | |
private final LineBreaker out; |
58 | |
|
59 | |
private final String sinkCommands; |
60 | |
|
61 | |
private final String preamble; |
62 | |
|
63 | |
private boolean titleFlag; |
64 | |
|
65 | |
private int numberedListNesting; |
66 | |
|
67 | |
private boolean verbatimFlag; |
68 | |
|
69 | |
private boolean figureFlag; |
70 | |
|
71 | |
private boolean tableFlag; |
72 | |
|
73 | |
private boolean gridFlag; |
74 | |
|
75 | |
private int[] cellJustif; |
76 | |
|
77 | |
private int cellCount; |
78 | |
|
79 | |
private boolean isTitle; |
80 | |
|
81 | |
private String title; |
82 | |
|
83 | |
|
84 | |
|
85 | |
|
86 | |
|
87 | |
|
88 | |
|
89 | |
|
90 | |
|
91 | |
|
92 | |
|
93 | |
protected LatexSink( Writer out ) |
94 | |
{ |
95 | 32 | this( out, null, null ); |
96 | 32 | } |
97 | |
|
98 | |
|
99 | |
|
100 | |
|
101 | |
|
102 | |
|
103 | |
|
104 | |
|
105 | |
|
106 | |
protected LatexSink( Writer out, String sinkCommands, String preamble ) |
107 | |
{ |
108 | 32 | this( out, sinkCommands, preamble, false ); |
109 | 32 | } |
110 | |
|
111 | |
|
112 | |
|
113 | |
|
114 | |
|
115 | |
|
116 | |
|
117 | |
|
118 | |
|
119 | |
|
120 | |
|
121 | |
protected LatexSink( Writer out, String sinkCommands, String preamble, boolean fragmentDocument ) |
122 | 32 | { |
123 | 32 | this.out = new LineBreaker( out ); |
124 | |
|
125 | 32 | if ( sinkCommands == null ) |
126 | |
{ |
127 | 32 | sinkCommands = defaultSinkCommands(); |
128 | |
} |
129 | 32 | if ( preamble == null ) |
130 | |
{ |
131 | 32 | preamble = defaultPreamble(); |
132 | |
} |
133 | |
|
134 | 32 | this.sinkCommands = sinkCommands; |
135 | 32 | this.preamble = preamble; |
136 | 32 | this.fragmentDocument = fragmentDocument; |
137 | |
|
138 | 32 | init(); |
139 | 32 | } |
140 | |
|
141 | |
|
142 | |
|
143 | |
|
144 | |
|
145 | |
|
146 | |
|
147 | |
|
148 | |
|
149 | |
|
150 | |
protected String getDocumentStart() |
151 | |
{ |
152 | 2 | return "\\documentclass[a4paper]{article}" + EOL + EOL; |
153 | |
} |
154 | |
|
155 | |
|
156 | |
|
157 | |
|
158 | |
|
159 | |
|
160 | |
protected String getDocumentBegin() |
161 | |
{ |
162 | 2 | return "\\begin{document}" + EOL + EOL; |
163 | |
} |
164 | |
|
165 | |
|
166 | |
|
167 | |
|
168 | |
|
169 | |
|
170 | |
protected String getDocumentEnd() |
171 | |
{ |
172 | 2 | return "\\end{document}" + EOL; |
173 | |
} |
174 | |
|
175 | |
|
176 | |
|
177 | |
|
178 | |
|
179 | |
|
180 | |
|
181 | |
|
182 | |
public void head() |
183 | |
{ |
184 | 2 | head( null ); |
185 | 2 | } |
186 | |
|
187 | |
|
188 | |
public void head( SinkEventAttributes attributes ) |
189 | |
{ |
190 | 2 | init(); |
191 | |
|
192 | 2 | if ( !fragmentDocument ) |
193 | |
{ |
194 | 2 | markup( sinkCommands ); |
195 | |
|
196 | 2 | markup( getDocumentStart() ); |
197 | |
|
198 | 2 | markup( preamble ); |
199 | |
|
200 | 2 | markup( getDocumentBegin() ); |
201 | |
} |
202 | 2 | } |
203 | |
|
204 | |
|
205 | |
|
206 | |
|
207 | |
public void body() |
208 | |
{ |
209 | 2 | body( null ); |
210 | 2 | } |
211 | |
|
212 | |
|
213 | |
public void body( SinkEventAttributes attributes ) |
214 | |
{ |
215 | 2 | if ( titleFlag ) |
216 | |
{ |
217 | 1 | if ( fragmentDocument ) |
218 | |
{ |
219 | 0 | markup( "\\section" ); |
220 | |
} |
221 | |
else |
222 | |
{ |
223 | 1 | titleFlag = false; |
224 | 1 | markup( "\\maketitle" + EOL + EOL ); |
225 | |
} |
226 | |
} |
227 | 2 | } |
228 | |
|
229 | |
|
230 | |
|
231 | |
|
232 | |
public void body_() |
233 | |
{ |
234 | 2 | if ( !fragmentDocument ) |
235 | |
{ |
236 | 2 | markup( getDocumentEnd() ); |
237 | |
} |
238 | |
|
239 | 2 | flush(); |
240 | 2 | } |
241 | |
|
242 | |
|
243 | |
|
244 | |
|
245 | |
public void title() |
246 | |
{ |
247 | 2 | title( null ); |
248 | 2 | } |
249 | |
|
250 | |
|
251 | |
public void title( SinkEventAttributes attributes ) |
252 | |
{ |
253 | 2 | if ( !fragmentDocument ) |
254 | |
{ |
255 | 2 | titleFlag = true; |
256 | 2 | markup( "\\title{" ); |
257 | |
} |
258 | |
else |
259 | |
{ |
260 | 0 | ignoreText = true; |
261 | |
} |
262 | 2 | } |
263 | |
|
264 | |
|
265 | |
|
266 | |
|
267 | |
public void title_() |
268 | |
{ |
269 | 2 | if ( !fragmentDocument ) |
270 | |
{ |
271 | 2 | markup( "}" + EOL ); |
272 | |
} |
273 | |
else |
274 | |
{ |
275 | 0 | ignoreText = false; |
276 | |
} |
277 | 2 | } |
278 | |
|
279 | |
|
280 | |
|
281 | |
|
282 | |
public void author() |
283 | |
{ |
284 | 2 | author( null ); |
285 | 2 | } |
286 | |
|
287 | |
|
288 | |
public void author( SinkEventAttributes attributes ) |
289 | |
{ |
290 | 2 | if ( !fragmentDocument ) |
291 | |
{ |
292 | 2 | markup( "\\author{" ); |
293 | |
} |
294 | |
else |
295 | |
{ |
296 | 0 | ignoreText = true; |
297 | |
} |
298 | 2 | } |
299 | |
|
300 | |
|
301 | |
|
302 | |
|
303 | |
public void author_() |
304 | |
{ |
305 | 2 | if ( !fragmentDocument ) |
306 | |
{ |
307 | 2 | markup( "}" + EOL ); |
308 | |
} |
309 | |
else |
310 | |
{ |
311 | 0 | ignoreText = false; |
312 | |
} |
313 | 2 | } |
314 | |
|
315 | |
|
316 | |
|
317 | |
|
318 | |
public void date() |
319 | |
{ |
320 | 2 | date( null ); |
321 | 2 | } |
322 | |
|
323 | |
|
324 | |
public void date( SinkEventAttributes attributes ) |
325 | |
{ |
326 | 2 | if ( !fragmentDocument ) |
327 | |
{ |
328 | 2 | markup( "\\date{" ); |
329 | |
} |
330 | |
else |
331 | |
{ |
332 | 0 | ignoreText = true; |
333 | |
} |
334 | 2 | } |
335 | |
|
336 | |
|
337 | |
|
338 | |
|
339 | |
public void date_() |
340 | |
{ |
341 | 2 | if ( !fragmentDocument ) |
342 | |
{ |
343 | 2 | markup( "}" + EOL ); |
344 | |
} |
345 | |
else |
346 | |
{ |
347 | 0 | ignoreText = false; |
348 | |
} |
349 | 2 | } |
350 | |
|
351 | |
|
352 | |
public void sectionTitle( int level, SinkEventAttributes attributes ) |
353 | |
{ |
354 | 10 | isTitle = true; |
355 | 10 | } |
356 | |
|
357 | |
|
358 | |
public void sectionTitle_( int level ) |
359 | |
{ |
360 | 10 | String command = ""; |
361 | 10 | switch ( level ) |
362 | |
{ |
363 | |
case SECTION_LEVEL_1: |
364 | 2 | command = "section"; |
365 | 2 | break; |
366 | |
case SECTION_LEVEL_2: |
367 | 2 | command = "subsection"; |
368 | 2 | break; |
369 | |
case SECTION_LEVEL_3: |
370 | 2 | command = "subsubsection"; |
371 | 2 | break; |
372 | |
case SECTION_LEVEL_4: |
373 | 2 | command = "paragraph"; |
374 | 2 | break; |
375 | |
case SECTION_LEVEL_5: |
376 | 2 | command = "subparagraph"; |
377 | 2 | break; |
378 | |
default: |
379 | 0 | throw new IllegalArgumentException( "Not a section level: " + level ); |
380 | |
} |
381 | |
|
382 | 10 | isTitle = false; |
383 | |
|
384 | 10 | if ( StringUtils.isNotEmpty( title ) ) |
385 | |
{ |
386 | 10 | markup( EOL + "\\" + command + "{" + title + "}" + EOL ); |
387 | |
|
388 | 10 | title = null; |
389 | |
} |
390 | 10 | } |
391 | |
|
392 | |
|
393 | |
|
394 | |
|
395 | |
|
396 | |
|
397 | |
|
398 | |
|
399 | |
public void sectionTitle1() |
400 | |
{ |
401 | 2 | sectionTitle( SECTION_LEVEL_1, null ); |
402 | 2 | } |
403 | |
|
404 | |
|
405 | |
|
406 | |
|
407 | |
public void sectionTitle1_() |
408 | |
{ |
409 | 2 | sectionTitle_( SECTION_LEVEL_1 ); |
410 | 2 | } |
411 | |
|
412 | |
|
413 | |
|
414 | |
|
415 | |
|
416 | |
|
417 | |
|
418 | |
|
419 | |
public void sectionTitle2() |
420 | |
{ |
421 | 2 | sectionTitle( SECTION_LEVEL_2, null ); |
422 | 2 | } |
423 | |
|
424 | |
|
425 | |
|
426 | |
|
427 | |
public void sectionTitle2_() |
428 | |
{ |
429 | 2 | sectionTitle_( SECTION_LEVEL_2 ); |
430 | 2 | } |
431 | |
|
432 | |
|
433 | |
|
434 | |
|
435 | |
|
436 | |
|
437 | |
|
438 | |
|
439 | |
public void sectionTitle3() |
440 | |
{ |
441 | 2 | sectionTitle( SECTION_LEVEL_3, null ); |
442 | 2 | } |
443 | |
|
444 | |
|
445 | |
|
446 | |
|
447 | |
public void sectionTitle3_() |
448 | |
{ |
449 | 2 | sectionTitle_( SECTION_LEVEL_3 ); |
450 | 2 | } |
451 | |
|
452 | |
|
453 | |
|
454 | |
|
455 | |
|
456 | |
|
457 | |
|
458 | |
|
459 | |
public void sectionTitle4() |
460 | |
{ |
461 | 2 | sectionTitle( SECTION_LEVEL_4, null ); |
462 | 2 | } |
463 | |
|
464 | |
|
465 | |
|
466 | |
|
467 | |
public void sectionTitle4_() |
468 | |
{ |
469 | 2 | sectionTitle_( SECTION_LEVEL_4 ); |
470 | 2 | } |
471 | |
|
472 | |
|
473 | |
|
474 | |
|
475 | |
|
476 | |
|
477 | |
|
478 | |
|
479 | |
public void sectionTitle5() |
480 | |
{ |
481 | 2 | sectionTitle( SECTION_LEVEL_5, null ); |
482 | 2 | } |
483 | |
|
484 | |
|
485 | |
|
486 | |
|
487 | |
public void sectionTitle5_() |
488 | |
{ |
489 | 2 | sectionTitle_( SECTION_LEVEL_5 ); |
490 | 2 | } |
491 | |
|
492 | |
|
493 | |
|
494 | |
|
495 | |
|
496 | |
|
497 | |
|
498 | |
|
499 | |
public void list() |
500 | |
{ |
501 | 3 | list( null ); |
502 | 3 | } |
503 | |
|
504 | |
|
505 | |
public void list( SinkEventAttributes attributes ) |
506 | |
{ |
507 | 3 | markup( EOL + "\\begin{itemize}" ); |
508 | 3 | } |
509 | |
|
510 | |
|
511 | |
|
512 | |
|
513 | |
public void list_() |
514 | |
{ |
515 | 3 | markup( EOL + "\\end{itemize}" + EOL ); |
516 | 3 | } |
517 | |
|
518 | |
|
519 | |
|
520 | |
|
521 | |
public void listItem() |
522 | |
{ |
523 | 6 | listItem( null ); |
524 | 6 | } |
525 | |
|
526 | |
|
527 | |
public void listItem( SinkEventAttributes attributes ) |
528 | |
{ |
529 | 6 | markup( EOL + "\\item " ); |
530 | 6 | } |
531 | |
|
532 | |
|
533 | |
|
534 | |
|
535 | |
public void numberedList( int numbering ) |
536 | |
{ |
537 | 3 | numberedList( numbering, null ); |
538 | 3 | } |
539 | |
|
540 | |
|
541 | |
public void numberedList( int numbering, SinkEventAttributes attributes ) |
542 | |
{ |
543 | 3 | ++numberedListNesting; |
544 | |
|
545 | |
String counter; |
546 | 3 | switch ( numberedListNesting ) |
547 | |
{ |
548 | |
case 1: |
549 | 2 | counter = "enumi"; |
550 | 2 | break; |
551 | |
case 2: |
552 | 1 | counter = "enumii"; |
553 | 1 | break; |
554 | |
case 3: |
555 | 0 | counter = "enumiii"; |
556 | 0 | break; |
557 | |
case 4: |
558 | |
default: |
559 | 0 | counter = "enumiv"; |
560 | |
} |
561 | |
|
562 | |
String style; |
563 | 3 | switch ( numbering ) |
564 | |
{ |
565 | |
case NUMBERING_UPPER_ALPHA: |
566 | 1 | style = "Alph"; |
567 | 1 | break; |
568 | |
case NUMBERING_LOWER_ALPHA: |
569 | 0 | style = "alph"; |
570 | 0 | break; |
571 | |
case NUMBERING_UPPER_ROMAN: |
572 | 0 | style = "Roman"; |
573 | 0 | break; |
574 | |
case NUMBERING_LOWER_ROMAN: |
575 | 1 | style = "roman"; |
576 | 1 | break; |
577 | |
case NUMBERING_DECIMAL: |
578 | |
default: |
579 | 1 | style = "arabic"; |
580 | |
} |
581 | |
|
582 | 3 | markup( EOL + "\\begin{enumerate}" + EOL ); |
583 | 3 | markup( "\\renewcommand{\\the" + counter + "}{\\" + style + "{" + counter + "}}" + EOL ); |
584 | 3 | } |
585 | |
|
586 | |
|
587 | |
|
588 | |
|
589 | |
public void numberedList_() |
590 | |
{ |
591 | 3 | markup( EOL + "\\end{enumerate}" + EOL ); |
592 | 3 | --numberedListNesting; |
593 | 3 | } |
594 | |
|
595 | |
|
596 | |
|
597 | |
|
598 | |
public void numberedListItem() |
599 | |
{ |
600 | 5 | numberedListItem( null ); |
601 | 5 | } |
602 | |
|
603 | |
|
604 | |
public void numberedListItem( SinkEventAttributes attributes ) |
605 | |
{ |
606 | 5 | markup( "\\item " ); |
607 | 5 | } |
608 | |
|
609 | |
|
610 | |
|
611 | |
|
612 | |
public void definitionList() |
613 | |
{ |
614 | 2 | definitionList( null ); |
615 | 2 | } |
616 | |
|
617 | |
|
618 | |
public void definitionList( SinkEventAttributes attributes ) |
619 | |
{ |
620 | 2 | markup( EOL + "\\begin{description}" ); |
621 | 2 | } |
622 | |
|
623 | |
|
624 | |
|
625 | |
|
626 | |
public void definitionList_() |
627 | |
{ |
628 | 2 | markup( EOL + "\\end{description}" + EOL ); |
629 | 2 | } |
630 | |
|
631 | |
|
632 | |
|
633 | |
|
634 | |
public void definedTerm() |
635 | |
{ |
636 | 3 | definedTerm( null ); |
637 | 3 | } |
638 | |
|
639 | |
|
640 | |
public void definedTerm( SinkEventAttributes attributes ) |
641 | |
{ |
642 | 3 | markup( EOL + "\\item[\\mbox{" ); |
643 | 3 | } |
644 | |
|
645 | |
|
646 | |
|
647 | |
|
648 | |
public void definedTerm_() |
649 | |
{ |
650 | 3 | markup( "}] " ); |
651 | 3 | } |
652 | |
|
653 | |
|
654 | |
public void definitionListItem() |
655 | |
{ |
656 | 3 | definitionListItem( null ); |
657 | 3 | } |
658 | |
|
659 | |
|
660 | |
public void definitionListItem( SinkEventAttributes attributes ) |
661 | |
{ |
662 | |
|
663 | 3 | } |
664 | |
|
665 | |
|
666 | |
public void definitionListItem_() |
667 | |
{ |
668 | |
|
669 | 3 | } |
670 | |
|
671 | |
|
672 | |
public void definition() |
673 | |
{ |
674 | 3 | definition( null ); |
675 | 3 | } |
676 | |
|
677 | |
|
678 | |
public void definition( SinkEventAttributes attributes ) |
679 | |
{ |
680 | |
|
681 | 3 | } |
682 | |
|
683 | |
|
684 | |
public void definition_() |
685 | |
{ |
686 | |
|
687 | 3 | } |
688 | |
|
689 | |
|
690 | |
|
691 | |
|
692 | |
|
693 | |
|
694 | |
|
695 | |
|
696 | |
public void figure() |
697 | |
{ |
698 | 1 | figure( null ); |
699 | 1 | } |
700 | |
|
701 | |
|
702 | |
public void figure( SinkEventAttributes attributes ) |
703 | |
{ |
704 | 2 | figureFlag = true; |
705 | 2 | markup( EOL + "\\begin{figure}[htb]" + EOL ); |
706 | 2 | } |
707 | |
|
708 | |
|
709 | |
|
710 | |
|
711 | |
public void figure_() |
712 | |
{ |
713 | 2 | markup( "\\end{figure}" + EOL ); |
714 | 2 | figureFlag = false; |
715 | 2 | } |
716 | |
|
717 | |
|
718 | |
|
719 | |
|
720 | |
public void figureGraphics( String name ) |
721 | |
{ |
722 | 1 | figureGraphics( name, null ); |
723 | 1 | } |
724 | |
|
725 | |
|
726 | |
public void figureGraphics( String src, SinkEventAttributes attributes ) |
727 | |
{ |
728 | 2 | if ( !src.toLowerCase( Locale.ENGLISH ).endsWith( ".eps" ) ) |
729 | |
{ |
730 | 2 | getLog().warn( "[Latex Sink] Found non-eps figure graphics!" ); |
731 | |
} |
732 | |
|
733 | 2 | markup( "\\begin{center}" + EOL ); |
734 | 2 | markup( "\\includegraphics{" + src + "}" + EOL ); |
735 | 2 | markup( "\\end{center}" + EOL ); |
736 | 2 | } |
737 | |
|
738 | |
|
739 | |
|
740 | |
|
741 | |
public void figureCaption() |
742 | |
{ |
743 | 1 | figureCaption( null ); |
744 | 1 | } |
745 | |
|
746 | |
|
747 | |
public void figureCaption( SinkEventAttributes attributes ) |
748 | |
{ |
749 | 2 | markup( "\\caption{" ); |
750 | 2 | } |
751 | |
|
752 | |
|
753 | |
|
754 | |
|
755 | |
public void figureCaption_() |
756 | |
{ |
757 | 2 | markup( "}" + EOL ); |
758 | 2 | } |
759 | |
|
760 | |
|
761 | |
|
762 | |
|
763 | |
|
764 | |
|
765 | |
|
766 | |
|
767 | |
public void table() |
768 | |
{ |
769 | 4 | table( null ); |
770 | 4 | } |
771 | |
|
772 | |
|
773 | |
public void table( SinkEventAttributes attributes ) |
774 | |
{ |
775 | 4 | tableFlag = true; |
776 | 4 | markup( EOL + "\\begin{table}[htp]" + EOL ); |
777 | 4 | } |
778 | |
|
779 | |
|
780 | |
|
781 | |
|
782 | |
public void table_() |
783 | |
{ |
784 | 4 | markup( "\\end{table}" + EOL ); |
785 | 4 | tableFlag = false; |
786 | 4 | } |
787 | |
|
788 | |
|
789 | |
|
790 | |
|
791 | |
public void tableRows( int[] justification, boolean grid ) |
792 | |
|
793 | |
{ |
794 | 4 | StringBuffer justif = new StringBuffer(); |
795 | 12 | for ( int i = 0; i < justification.length; ++i ) |
796 | |
{ |
797 | 8 | if ( grid ) |
798 | |
{ |
799 | 5 | justif.append( '|' ); |
800 | |
} |
801 | 8 | switch ( justification[i] ) |
802 | |
{ |
803 | |
case Sink.JUSTIFY_CENTER: |
804 | 6 | justif.append( 'c' ); |
805 | 6 | break; |
806 | |
case Sink.JUSTIFY_LEFT: |
807 | 1 | justif.append( 'l' ); |
808 | 1 | break; |
809 | |
case Sink.JUSTIFY_RIGHT: |
810 | 1 | justif.append( 'r' ); |
811 | 1 | break; |
812 | |
default: |
813 | |
break; |
814 | |
} |
815 | |
} |
816 | 4 | if ( grid ) |
817 | |
{ |
818 | 2 | justif.append( '|' ); |
819 | |
} |
820 | |
|
821 | 4 | markup( "\\begin{center}" + EOL ); |
822 | 4 | markup( "\\begin{tabular}{" + justif.toString() + "}" + EOL ); |
823 | 4 | if ( grid ) |
824 | |
{ |
825 | 2 | markup( "\\hline" + EOL ); |
826 | |
} |
827 | 4 | gridFlag = grid; |
828 | 4 | cellJustif = justification; |
829 | 4 | } |
830 | |
|
831 | |
|
832 | |
|
833 | |
|
834 | |
public void tableRows_() |
835 | |
{ |
836 | 4 | markup( "\\end{tabular}" + EOL ); |
837 | 4 | markup( "\\end{center}" + EOL ); |
838 | |
|
839 | 4 | gridFlag = false; |
840 | 4 | cellJustif = null; |
841 | 4 | } |
842 | |
|
843 | |
|
844 | |
|
845 | |
|
846 | |
public void tableRow() |
847 | |
{ |
848 | 7 | tableRow( null ); |
849 | 7 | } |
850 | |
|
851 | |
|
852 | |
public void tableRow( SinkEventAttributes attributes ) |
853 | |
{ |
854 | 7 | cellCount = 0; |
855 | 7 | } |
856 | |
|
857 | |
|
858 | |
|
859 | |
|
860 | |
public void tableRow_() |
861 | |
{ |
862 | 7 | markup( "\\\\" + EOL ); |
863 | 7 | if ( gridFlag || lastCellWasHeader ) |
864 | |
{ |
865 | 4 | markup( "\\hline" + EOL ); |
866 | |
} |
867 | 7 | cellCount = 0; |
868 | 7 | lastCellWasHeader = false; |
869 | 7 | } |
870 | |
|
871 | |
|
872 | |
|
873 | |
|
874 | |
public void tableCell() |
875 | |
{ |
876 | 13 | tableCell( (SinkEventAttributes) null ); |
877 | 13 | } |
878 | |
|
879 | |
|
880 | |
public void tableCell( String width ) |
881 | |
{ |
882 | 0 | SinkEventAttributeSet att = new SinkEventAttributeSet(); |
883 | 0 | att.addAttribute( javax.swing.text.html.HTML.Attribute.WIDTH, width ); |
884 | |
|
885 | 0 | tableCell( att ); |
886 | 0 | } |
887 | |
|
888 | |
|
889 | |
public void tableCell( SinkEventAttributes attributes ) |
890 | |
{ |
891 | 15 | tableCell( false ); |
892 | 15 | } |
893 | |
|
894 | |
|
895 | |
|
896 | |
|
897 | |
public void tableCell_() |
898 | |
{ |
899 | 15 | markup( "\\end{tabular}" ); |
900 | 15 | ++cellCount; |
901 | 15 | } |
902 | |
|
903 | |
|
904 | |
|
905 | |
|
906 | |
public void tableHeaderCell() |
907 | |
{ |
908 | 2 | tableCell( (SinkEventAttributes) null ); |
909 | 2 | } |
910 | |
|
911 | |
|
912 | |
public void tableHeaderCell( String width ) |
913 | |
{ |
914 | 0 | SinkEventAttributeSet att = new SinkEventAttributeSet(); |
915 | 0 | att.addAttribute( javax.swing.text.html.HTML.Attribute.WIDTH, width ); |
916 | |
|
917 | 0 | tableHeaderCell( att ); |
918 | 0 | } |
919 | |
|
920 | |
|
921 | |
public void tableHeaderCell( SinkEventAttributes attributes ) |
922 | |
{ |
923 | 0 | tableCell( true ); |
924 | 0 | } |
925 | |
|
926 | |
|
927 | |
|
928 | |
|
929 | |
public void tableHeaderCell_() |
930 | |
{ |
931 | 2 | tableCell_(); |
932 | 2 | } |
933 | |
|
934 | 32 | private boolean lastCellWasHeader = false; |
935 | |
|
936 | |
|
937 | |
|
938 | |
|
939 | |
|
940 | |
|
941 | |
private void tableCell( boolean header ) |
942 | |
{ |
943 | 15 | lastCellWasHeader = header; |
944 | |
|
945 | 15 | if ( cellCount > 0 ) |
946 | |
{ |
947 | 8 | markup( " &" + EOL ); |
948 | |
} |
949 | |
|
950 | |
char justif; |
951 | 15 | switch ( cellJustif[cellCount] ) |
952 | |
{ |
953 | |
case Sink.JUSTIFY_LEFT: |
954 | 2 | justif = 'l'; |
955 | 2 | break; |
956 | |
case Sink.JUSTIFY_RIGHT: |
957 | 2 | justif = 'r'; |
958 | 2 | break; |
959 | |
case Sink.JUSTIFY_CENTER: |
960 | |
default: |
961 | 11 | justif = 'c'; |
962 | |
break; |
963 | |
} |
964 | 15 | markup( "\\begin{tabular}[t]{" + justif + "}" ); |
965 | 15 | } |
966 | |
|
967 | |
|
968 | |
|
969 | |
|
970 | |
public void tableCaption() |
971 | |
{ |
972 | 2 | tableCaption( null ); |
973 | 2 | } |
974 | |
|
975 | |
|
976 | |
public void tableCaption( SinkEventAttributes attributes ) |
977 | |
{ |
978 | 2 | markup( "\\caption{" ); |
979 | 2 | } |
980 | |
|
981 | |
|
982 | |
|
983 | |
|
984 | |
public void tableCaption_() |
985 | |
{ |
986 | 2 | markup( "}" + EOL ); |
987 | 2 | } |
988 | |
|
989 | |
|
990 | |
|
991 | |
|
992 | |
public void paragraph() |
993 | |
{ |
994 | 15 | paragraph( null ); |
995 | 15 | } |
996 | |
|
997 | |
|
998 | |
public void paragraph( SinkEventAttributes attributes ) |
999 | |
{ |
1000 | 15 | markup( EOL + EOL ); |
1001 | 15 | } |
1002 | |
|
1003 | |
|
1004 | |
|
1005 | |
|
1006 | |
public void paragraph_() |
1007 | |
{ |
1008 | 15 | markup( EOL ); |
1009 | 15 | } |
1010 | |
|
1011 | |
|
1012 | |
|
1013 | |
|
1014 | |
public void verbatim( boolean boxed ) |
1015 | |
{ |
1016 | 0 | verbatim( boxed ? SinkEventAttributeSet.BOXED : null ); |
1017 | 0 | } |
1018 | |
|
1019 | |
|
1020 | |
public void verbatim( SinkEventAttributes attributes ) |
1021 | |
{ |
1022 | 3 | boolean boxed = false; |
1023 | |
|
1024 | 3 | if ( attributes != null && attributes.isDefined( SinkEventAttributes.DECORATION ) ) |
1025 | |
{ |
1026 | 3 | boxed = "boxed".equals( |
1027 | |
attributes.getAttribute( SinkEventAttributes.DECORATION ) ); |
1028 | |
} |
1029 | |
|
1030 | 3 | markup( EOL + "\\begin{small}" + EOL ); |
1031 | |
|
1032 | 3 | if ( boxed ) |
1033 | |
{ |
1034 | 3 | markup( "\\begin{Verbatim}[frame=single]" + EOL ); |
1035 | |
} |
1036 | |
else |
1037 | |
{ |
1038 | 0 | markup( "\\begin{Verbatim}" + EOL ); |
1039 | |
} |
1040 | |
|
1041 | 3 | verbatimFlag = true; |
1042 | 3 | } |
1043 | |
|
1044 | |
|
1045 | |
|
1046 | |
|
1047 | |
public void verbatim_() |
1048 | |
{ |
1049 | 3 | markup( EOL + "\\end{Verbatim}" + EOL ); |
1050 | 3 | markup( "\\end{small}" + EOL ); |
1051 | |
|
1052 | 3 | verbatimFlag = false; |
1053 | 3 | } |
1054 | |
|
1055 | |
|
1056 | |
|
1057 | |
|
1058 | |
public void horizontalRule() |
1059 | |
{ |
1060 | 2 | horizontalRule( null ); |
1061 | 2 | } |
1062 | |
|
1063 | |
|
1064 | |
public void horizontalRule( SinkEventAttributes attributes ) |
1065 | |
{ |
1066 | 2 | markup( EOL + "\\begin{center}\\rule[0.5ex]{\\linewidth}{1pt}\\end{center}" + EOL ); |
1067 | 2 | } |
1068 | |
|
1069 | |
|
1070 | |
|
1071 | |
|
1072 | |
public void pageBreak() |
1073 | |
{ |
1074 | 2 | markup( EOL + "\\newpage" + EOL ); |
1075 | 2 | } |
1076 | |
|
1077 | |
|
1078 | |
|
1079 | |
|
1080 | |
public void anchor( String name ) |
1081 | |
{ |
1082 | 2 | anchor( name, null ); |
1083 | 2 | } |
1084 | |
|
1085 | |
|
1086 | |
public void anchor( String name, SinkEventAttributes attributes ) |
1087 | |
{ |
1088 | 2 | markup( "\\hypertarget{" + name + "}{" ); |
1089 | 2 | } |
1090 | |
|
1091 | |
|
1092 | |
|
1093 | |
|
1094 | |
public void anchor_() |
1095 | |
{ |
1096 | 2 | markup( "}" ); |
1097 | 2 | } |
1098 | |
|
1099 | |
|
1100 | |
|
1101 | |
|
1102 | |
public void link( String name ) |
1103 | |
{ |
1104 | 5 | link( name, null ); |
1105 | 5 | } |
1106 | |
|
1107 | |
|
1108 | |
public void link( String name, SinkEventAttributes attributes ) |
1109 | |
{ |
1110 | |
|
1111 | 5 | if ( DoxiaUtils.isExternalLink( name ) ) |
1112 | |
{ |
1113 | 2 | markup( "\\href{" + name + "}{" ); |
1114 | |
} |
1115 | |
else |
1116 | |
{ |
1117 | 3 | markup( "\\hyperlink{" + name + "}{" ); |
1118 | |
} |
1119 | 5 | } |
1120 | |
|
1121 | |
|
1122 | |
|
1123 | |
|
1124 | |
public void link_() |
1125 | |
{ |
1126 | 5 | markup( "}" ); |
1127 | 5 | } |
1128 | |
|
1129 | |
|
1130 | |
|
1131 | |
|
1132 | |
public void italic() |
1133 | |
{ |
1134 | 2 | markup( "\\textit{" ); |
1135 | 2 | } |
1136 | |
|
1137 | |
|
1138 | |
|
1139 | |
|
1140 | |
public void italic_() |
1141 | |
{ |
1142 | 2 | markup( "}" ); |
1143 | 2 | } |
1144 | |
|
1145 | |
|
1146 | |
|
1147 | |
|
1148 | |
public void bold() |
1149 | |
{ |
1150 | 2 | markup( "\\textbf{" ); |
1151 | 2 | } |
1152 | |
|
1153 | |
|
1154 | |
|
1155 | |
|
1156 | |
public void bold_() |
1157 | |
{ |
1158 | 2 | markup( "}" ); |
1159 | 2 | } |
1160 | |
|
1161 | |
|
1162 | |
|
1163 | |
|
1164 | |
public void monospaced() |
1165 | |
{ |
1166 | 2 | markup( "\\texttt{\\small " ); |
1167 | 2 | } |
1168 | |
|
1169 | |
|
1170 | |
|
1171 | |
|
1172 | |
public void monospaced_() |
1173 | |
{ |
1174 | 2 | markup( "}" ); |
1175 | 2 | } |
1176 | |
|
1177 | |
|
1178 | |
|
1179 | |
|
1180 | |
public void lineBreak() |
1181 | |
{ |
1182 | 18 | lineBreak( null ); |
1183 | 18 | } |
1184 | |
|
1185 | |
|
1186 | |
public void lineBreak( SinkEventAttributes attributes ) |
1187 | |
{ |
1188 | 18 | markup( ( figureFlag || tableFlag || titleFlag || verbatimFlag ) ? EOL : "\\newline" + EOL ); |
1189 | 18 | } |
1190 | |
|
1191 | |
|
1192 | |
|
1193 | |
|
1194 | |
public void nonBreakingSpace() |
1195 | |
{ |
1196 | 3 | markup( "~" ); |
1197 | 3 | } |
1198 | |
|
1199 | |
|
1200 | |
|
1201 | |
|
1202 | |
public void text( String text ) |
1203 | |
{ |
1204 | 109 | text( text, null ); |
1205 | 109 | } |
1206 | |
|
1207 | |
|
1208 | |
public void text( String text, SinkEventAttributes attributes ) |
1209 | |
{ |
1210 | 110 | if ( ignoreText ) |
1211 | |
{ |
1212 | 0 | return; |
1213 | |
} |
1214 | 110 | if ( isTitle ) |
1215 | |
{ |
1216 | 10 | title = text; |
1217 | |
} |
1218 | 100 | else if ( verbatimFlag ) |
1219 | |
{ |
1220 | 3 | verbatimContent( text ); |
1221 | |
} |
1222 | |
else |
1223 | |
{ |
1224 | 97 | content( text ); |
1225 | |
} |
1226 | 110 | } |
1227 | |
|
1228 | |
|
1229 | |
public void rawText( String text ) |
1230 | |
{ |
1231 | 3 | verbatimContent( text ); |
1232 | 3 | } |
1233 | |
|
1234 | |
|
1235 | |
public void comment( String comment ) |
1236 | |
{ |
1237 | 2 | rawText( EOL + "% " + comment ); |
1238 | 2 | } |
1239 | |
|
1240 | |
|
1241 | |
|
1242 | |
|
1243 | |
|
1244 | |
|
1245 | |
|
1246 | |
public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes ) |
1247 | |
{ |
1248 | 0 | getLog().warn( "[Latex Sink] Unknown Sink event: '" + name + "', ignoring!" ); |
1249 | 0 | } |
1250 | |
|
1251 | |
|
1252 | |
|
1253 | |
|
1254 | |
|
1255 | |
|
1256 | |
|
1257 | |
|
1258 | |
protected void markup( String text ) |
1259 | |
{ |
1260 | 255 | if ( text != null ) |
1261 | |
{ |
1262 | 255 | out.write( text, true ); |
1263 | |
} |
1264 | 255 | } |
1265 | |
|
1266 | |
|
1267 | |
|
1268 | |
|
1269 | |
|
1270 | |
|
1271 | |
protected void content( String text ) |
1272 | |
{ |
1273 | 97 | out.write( escaped( text ), false ); |
1274 | 97 | } |
1275 | |
|
1276 | |
|
1277 | |
|
1278 | |
|
1279 | |
|
1280 | |
|
1281 | |
protected void verbatimContent( String text ) |
1282 | |
{ |
1283 | 6 | out.write( text, true ); |
1284 | 6 | } |
1285 | |
|
1286 | |
|
1287 | |
|
1288 | |
|
1289 | |
|
1290 | |
|
1291 | |
|
1292 | |
|
1293 | |
|
1294 | |
public static String escaped( String text ) |
1295 | |
{ |
1296 | 102 | int length = text.length(); |
1297 | 102 | StringBuffer buffer = new StringBuffer( length ); |
1298 | |
|
1299 | 1217 | for ( int i = 0; i < length; ++i ) |
1300 | |
{ |
1301 | 1115 | char c = text.charAt( i ); |
1302 | 1115 | switch ( c ) |
1303 | |
{ |
1304 | |
case '-': |
1305 | |
case '<': |
1306 | |
case '>': |
1307 | 15 | buffer.append( "\\symbol{" ).append( (int) c ).append( "}" ); |
1308 | 15 | break; |
1309 | |
case '~': |
1310 | 2 | buffer.append( "\\textasciitilde " ); |
1311 | 2 | break; |
1312 | |
case '^': |
1313 | 0 | buffer.append( "\\textasciicircum " ); |
1314 | 0 | break; |
1315 | |
case '|': |
1316 | 0 | buffer.append( "\\textbar " ); |
1317 | 0 | break; |
1318 | |
case '\\': |
1319 | 2 | buffer.append( "\\textbackslash " ); |
1320 | 2 | break; |
1321 | |
case '$': |
1322 | 0 | buffer.append( "\\$" ); |
1323 | 0 | break; |
1324 | |
case '&': |
1325 | 0 | buffer.append( "\\&" ); |
1326 | 0 | break; |
1327 | |
case '%': |
1328 | 0 | buffer.append( "\\%" ); |
1329 | 0 | break; |
1330 | |
case '#': |
1331 | 0 | buffer.append( "\\#" ); |
1332 | 0 | break; |
1333 | |
case '{': |
1334 | 2 | buffer.append( "\\{" ); |
1335 | 2 | break; |
1336 | |
case '}': |
1337 | 2 | buffer.append( "\\}" ); |
1338 | 2 | break; |
1339 | |
case '_': |
1340 | 21 | buffer.append( "\\_" ); |
1341 | 21 | break; |
1342 | |
default: |
1343 | 1071 | buffer.append( c ); |
1344 | |
} |
1345 | |
} |
1346 | |
|
1347 | 102 | return buffer.toString(); |
1348 | |
} |
1349 | |
|
1350 | |
|
1351 | |
|
1352 | |
|
1353 | |
|
1354 | |
|
1355 | |
|
1356 | |
|
1357 | |
public void flush() |
1358 | |
{ |
1359 | 33 | out.flush(); |
1360 | 33 | } |
1361 | |
|
1362 | |
|
1363 | |
|
1364 | |
|
1365 | |
public void close() |
1366 | |
{ |
1367 | 31 | out.close(); |
1368 | |
|
1369 | 31 | init(); |
1370 | 31 | } |
1371 | |
|
1372 | |
|
1373 | |
|
1374 | |
|
1375 | |
|
1376 | |
|
1377 | |
|
1378 | |
|
1379 | |
|
1380 | |
|
1381 | |
|
1382 | |
private static InputStream getDefaultSinkCommands() |
1383 | |
throws IOException |
1384 | |
{ |
1385 | 33 | return LatexSink.class.getResource( "default_sink_commands.tex" ).openStream(); |
1386 | |
} |
1387 | |
|
1388 | |
|
1389 | |
|
1390 | |
|
1391 | |
|
1392 | |
|
1393 | |
|
1394 | |
private static InputStream getDefaultPreamble() |
1395 | |
throws IOException |
1396 | |
{ |
1397 | 33 | return LatexSink.class.getResource( "default_preamble.tex" ).openStream(); |
1398 | |
} |
1399 | |
|
1400 | |
|
1401 | |
|
1402 | |
|
1403 | |
|
1404 | |
|
1405 | |
protected String defaultSinkCommands() |
1406 | |
{ |
1407 | |
try |
1408 | |
{ |
1409 | 33 | return IOUtil.toString( getDefaultSinkCommands() ); |
1410 | |
} |
1411 | 0 | catch ( IOException ioe ) |
1412 | |
{ |
1413 | |
|
1414 | 0 | getLog().warn( "Could not read default LaTeX commands, the generated LaTeX file will not compile!" ); |
1415 | 0 | getLog().debug( ioe ); |
1416 | |
|
1417 | 0 | return ""; |
1418 | |
} |
1419 | |
} |
1420 | |
|
1421 | |
|
1422 | |
|
1423 | |
|
1424 | |
|
1425 | |
|
1426 | |
protected String defaultPreamble() |
1427 | |
{ |
1428 | |
try |
1429 | |
{ |
1430 | 33 | return IOUtil.toString( getDefaultPreamble() ); |
1431 | |
} |
1432 | 0 | catch ( IOException ioe ) |
1433 | |
{ |
1434 | |
|
1435 | 0 | getLog().warn( "Could not read default LaTeX preamble, the generated LaTeX file will not compile!" ); |
1436 | 0 | getLog().debug( ioe ); |
1437 | |
|
1438 | 0 | return ""; |
1439 | |
} |
1440 | |
} |
1441 | |
|
1442 | |
|
1443 | |
protected void init() |
1444 | |
{ |
1445 | 65 | super.init(); |
1446 | |
|
1447 | 65 | this.ignoreText = false; |
1448 | 65 | this.titleFlag = false; |
1449 | 65 | this.numberedListNesting = 0; |
1450 | 65 | this.verbatimFlag = false; |
1451 | 65 | this.figureFlag = false; |
1452 | 65 | this.tableFlag = false; |
1453 | 65 | this.gridFlag = false; |
1454 | 65 | this.cellJustif = null; |
1455 | 65 | this.cellCount = 0; |
1456 | 65 | this.isTitle = false; |
1457 | 65 | this.title = null; |
1458 | 65 | } |
1459 | |
} |