Added options to make Robodoc more customizable.
[robodoc.git] / Source / latex_generator.c
1 /*
2 Copyright (C) 1994-2007  Frans Slothouber, Jacco van Weert, Petteri Kettunen,
3 Bernd Koesling, Thomas Aglassinger, Anthon Pang, Stefan Kost, David Druffner,
4 Sasha Vasko, Kai Hofmann, Thierry Pierron, Friedrich Haase, and Gergely Budai.
5
6 This file is part of ROBODoc
7
8 ROBODoc is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21 */
22
23 /****h* ROBODoc/LaTeX_Generator
24  * FUNCTION
25  *   Generator for LaTeX output.  Supports singledoc mode.
26  *
27  *******
28  * TODO  More documentation.
29  */
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <ctype.h>
35
36 #include "generator.h"
37 #include "util.h"
38 #include "links.h"
39 #include "latex_generator.h"
40 #include "globals.h"
41 #include "robodoc.h"
42
43 #ifdef DMALLOC
44 #include <dmalloc.h>
45 #endif
46
47 static int          verbatim = FALSE;
48
49
50 /****f* LaTeX_Generator/RB_LaTeX_Generate_String
51  * FUNCTION
52  *   Write a string to the destination document, escaping
53  *   characters where necessary.
54  ******
55  */
56
57 void RB_LaTeX_Generate_String(
58     FILE *dest_doc,
59     char *a_string )
60 {
61     int                 i;
62     int                 l = strlen( a_string );
63     unsigned char       c;
64
65     for ( i = 0; i < l; i++ )
66     {
67         c = a_string[i];
68         RB_LaTeX_Generate_Char( dest_doc, c );
69     }
70 }
71
72
73 void RB_LaTeX_Generate_False_Link(
74     FILE *dest_doc,
75     char *name )
76 {
77     RB_LaTeX_Generate_String( dest_doc, name );
78 }
79
80 void RB_LaTeX_Generate_Item_Begin(
81     FILE *dest_doc )
82 {
83     USE( dest_doc );
84     /* Empty */
85 }
86
87 void RB_LaTeX_Generate_Item_End(
88     FILE *dest_doc )
89 {
90     USE( dest_doc );
91     /* Empty */
92 }
93
94 /* void */
95 /* RB_LaTeX_Generate_Item_Name( FILE* dest_doc, char *name ) */
96 /* { */
97 /*     RB_LaTeX_Generate_String( dest_doc, name ); */
98 /*     fprintf( dest_doc, "\n" ); */
99 /* } */
100
101
102 /* Lowtexx 21.09.2005 11:02 */
103 /* I think it looks better like this. This wastes less space in pdf-document. */
104 void RB_LaTeX_Generate_Item_Name(
105     FILE *dest_doc,
106     char *name )
107 {
108     fprintf( dest_doc, "\\textbf{" );
109     RB_LaTeX_Generate_String( dest_doc, name );
110
111     // In alternate format, item names stand alone (Thuffir)
112     if ( course_of_action.do_altlatex )
113         fprintf( dest_doc, "}\n" );
114     else
115         fprintf( dest_doc, ":}\\hspace{0.08in}" );
116 }
117
118
119 void RB_LaTeX_Generate_BeginSection(
120     FILE *dest_doc,
121     int depth,
122     char *name,
123     struct RB_header *header )
124 {
125     int                 i;
126
127     // Generate a new page for every section in alternate format
128     if ( course_of_action.do_altlatex )
129         fprintf( dest_doc, "\\newpage\n" );
130
131     // If \part enabled, we have a level deeper
132     // So enable the level '0'
133     if ( course_of_action.do_latexparts )
134         depth--;
135
136     switch ( depth )
137     {
138     case 0:
139         fprintf( dest_doc, "\\part{" );
140         break;
141     case 1:
142         fprintf( dest_doc, "\\section{" );
143         break;
144     case 2:
145         fprintf( dest_doc, "\\subsection{" );
146         break;
147     case 3:
148         fprintf( dest_doc, "\\subsubsection{" );
149         break;
150     default:
151         /* Too deep so just make it a subsubsection */
152         fprintf( dest_doc, "\\subsubsection{" );
153     }
154
155     // Print Header "First" name
156     RB_LaTeX_Generate_String( dest_doc, name );
157     // Print other names
158     for ( i = 1; i < header->no_names; i++ )
159     {
160         RB_LaTeX_Generate_String( dest_doc, ", " );
161         RB_LaTeX_Generate_String( dest_doc, header->names[i] );
162     }
163     fprintf( dest_doc, "}\n" );
164
165     // Print Parent if any
166     if ( header->parent )
167     {
168         fprintf( dest_doc, "\\textsl{[ " );
169         RB_LaTeX_Generate_String( dest_doc, header->parent->function_name );
170         fprintf( dest_doc, " ]}\n" );
171     }
172
173     // Print Header Type
174     fprintf( dest_doc, "\\textsl{[ " );
175     RB_LaTeX_Generate_String( dest_doc, header->htype->indexName );
176     fprintf( dest_doc, " ]}\n\n" );
177 }
178
179 void RB_LaTeX_Generate_EndSection(
180     FILE *dest_doc,
181     int depth,
182     char *name )
183 {
184     USE( dest_doc );
185     USE( depth );
186     USE( name );
187     /* Empty */
188 }
189
190 char               *RB_LaTeX_Get_Default_Extension(
191     void )
192 {
193     return ".tex";
194 }
195
196
197 /****f* LaTeX_Generator/RB_LaTeX_Generate_Doc_Start
198  * NAME
199  *   RB_LaTeX_Generate_Doc_Start --
200  *****
201  */
202
203 void RB_LaTeX_Generate_Doc_Start(
204     FILE *dest_doc,
205     char *src_name,
206     char *name,
207     char *charset )
208 {
209     fprintf( dest_doc, "%% Document: %s\n", name );
210     fprintf( dest_doc, "%% Source: %s\n", src_name );
211
212     if ( course_of_action.do_nogenwith )
213     {
214
215     }
216     else
217     {
218         fprintf( dest_doc, "%% " COMMENT_ROBODOC );
219 /* Documentation is the users not ours  fprintf( dest_doc, "%% " COMMENT_COPYRIGHT ); */
220     }
221
222     if ( course_of_action.do_headless )
223     {
224         /* The user wants a headless document, so we skip all
225          * initialization.  It is up to the user to put this in.
226          */
227     }
228     else
229     {
230         fprintf( dest_doc, "\\documentclass{article}\n" );
231         fprintf( dest_doc, "\\usepackage{makeidx}\n" );
232         fprintf( dest_doc, "\\usepackage{graphicx}\n" );
233
234         // Check if we have to use the inputenc package
235         if ( charset )
236         {
237             fprintf( dest_doc, "\\usepackage[%s]{inputenc}\n", charset );
238         }
239
240         // Alternate mode, works better with pdflatex and DIN A4 sheets
241         // At least for me :) (Thuffir)
242         if ( course_of_action.do_altlatex )
243         {
244             fprintf( dest_doc, "\\oddsidemargin 0 cm\n" );
245             fprintf( dest_doc, "\\evensidemargin 0 cm\n" );
246             fprintf( dest_doc, "\\topmargin 0 cm\n" );
247             fprintf( dest_doc, "\\textwidth 16 cm\n" );
248             fprintf( dest_doc, "\\textheight 22 cm\n" );
249         }
250         else
251         {
252             /* I guess this is unecessarry (same definitions twice ?)
253                fprintf( dest_doc, "\\oddsidemargin  0.15 in\n" );
254                fprintf( dest_doc, "\\evensidemargin 0.35 in\n" );
255                fprintf( dest_doc, "\\marginparwidth 1 in   \n" );
256              */
257
258             fprintf( dest_doc, "\\oddsidemargin 0.25 in \n" );
259             fprintf( dest_doc, "\\evensidemargin 0.25 in\n" );
260             fprintf( dest_doc, "\\marginparwidth 0.75 in\n" );
261             fprintf( dest_doc, "\\textwidth 5.875 in\n" );
262         }
263
264
265         fprintf( dest_doc, "\\setlength{\\parindent}{0in}\n" );
266         fprintf( dest_doc, "\\setlength{\\parskip}{.08in}\n\n" );
267
268         /* changed default header to use boldface (vs slant) */
269         fprintf( dest_doc, "\\pagestyle{headings}\n" );
270
271         // Set document title
272         fprintf( dest_doc, "\\title{%s}\n",
273                  document_title ? document_title : DEFAULT_DOCTITILE );
274
275         if ( course_of_action.do_nogenwith )
276         {
277             fprintf( dest_doc, "\\author{Documentation Generator}\n" );
278         }
279         else
280         {
281             fprintf( dest_doc, "\\author{%s}\n", COMMENT_ROBODOC );
282         }
283
284         fprintf( dest_doc, "\\makeindex\n" );
285         fprintf( dest_doc, "\\begin{document}\n" );
286         fprintf( dest_doc, "\\maketitle\n" );
287
288         // In alternate mode, we generate INDEX at the end of document
289         if ( course_of_action.do_altlatex )
290         {
291             fprintf( dest_doc, "\\newpage\n" );
292         }
293         else
294         {
295             fprintf( dest_doc, "\\printindex\n" );
296         }
297
298         /* autogenerate table of contents! */
299         fprintf( dest_doc, "\\tableofcontents\n" );
300
301         // We don't need this in alternate format, since every section begins
302         // with a \newpage (Thuffir)
303         if ( !( course_of_action.do_altlatex ) )
304             fprintf( dest_doc, "\\newpage\n" );
305
306         /* trick to disable the autogenerated \newpage */
307         fprintf( dest_doc, "\n" );
308     }
309 }
310
311 /****f* LaTeX_Generator/RB_LaTeX_Generate_Doc_End
312  * NAME
313  *   RB_LaTeX_Generate_Doc_End --
314  *****
315  */
316
317 void RB_LaTeX_Generate_Doc_End(
318     FILE *dest_doc,
319     char *name )
320 {
321     USE( name );
322
323     // In alternate mode, we generate INDEX at the end of document
324     if ( course_of_action.do_altlatex )
325     {
326         fprintf( dest_doc, "\\printindex\n" );
327     }
328
329     if ( course_of_action.do_footless )
330     {
331         /* The user does not want the foot of the
332          * document
333          */
334     }
335     else
336     {
337         fprintf( dest_doc, "\\end{document}\n" );
338     }
339 }
340
341
342 /****f* LaTeX_Generator/RB_LaTeX_Generate_Index_Entry
343  * FUNCTION
344  *   Creates a entry for the index.
345  *
346  *******
347  */
348
349 void RB_LaTeX_Generate_Index_Entry(
350     FILE *dest_doc,
351     struct RB_header *cur_header )
352 {
353     assert( cur_header->function_name );
354
355     fprintf( dest_doc, "\\index{unsorted!" );
356     RB_LaTeX_Generate_String( dest_doc, cur_header->function_name );
357     if ( cur_header->is_internal )
358     {
359         fprintf( dest_doc, "}\\index{internal\\_%s!",
360                  cur_header->htype->indexName );
361     }
362     else
363     {
364         fprintf( dest_doc, "}\\index{%s!", cur_header->htype->indexName );
365     }
366     RB_LaTeX_Generate_String( dest_doc, cur_header->function_name );
367     fprintf( dest_doc, "}\n" );
368 }
369
370 /****f* LaTeX_Generator/RB_LaTeX_Generate_Header_Start
371  * NAME
372  *   RB_LaTeX_Generate_Header_Start --
373  *****
374  */
375
376 void RB_LaTeX_Generate_Header_Start(
377     FILE *dest_doc,
378     struct RB_header *cur_header )
379 {
380     fprintf( dest_doc, "\\subsection{" );
381     RB_LaTeX_Generate_String( dest_doc, cur_header->name );
382     fprintf( dest_doc, "}\n" );
383 }
384
385
386 /****f* LaTeX_Generator/RB_LaTeX_Generate_Header_End
387  * NAME
388  *   RB_LaTeX_Generate_Header_End --
389  *****
390  */
391
392 void RB_LaTeX_Generate_Header_End(
393     FILE *dest_doc,
394     struct RB_header *cur_header )
395 {
396     USE( cur_header );
397     fputc( '\n', dest_doc );
398 }
399
400
401 /*x**f* LaTeX_Generator/RB_LaTeX_Generate_Index
402  * NAME
403  *   RB_LaTeX_Generate_Index --
404  *****
405  */
406
407 void RB_LaTeX_Generate_Index(
408     FILE *dest,
409     char *source )
410 {
411     /* TODO REMOVE */
412     USE( dest );
413     USE( source );
414     assert( 0 );
415 #if 0
416     RB_Generate_Doc_Start( dest, source, "Master File", 0 );
417     RB_Generate_LaTeX_Includes( dest );
418     RB_Generate_Doc_End( dest, source );
419 #endif
420 }
421
422
423 /****f* LaTeX_Generator/RB_LaTeX_Generate_Index_Table
424  * NAME
425  *   RB_LaTeX_Generate_Index_Table --
426  *****
427  */
428
429 void RB_LaTeX_Generate_Index_Table(
430     FILE *dest,
431     int type,
432     char *title )
433 {
434     USE( dest );
435     USE( type );
436     USE( title );
437
438     /* Empty */
439 }
440
441 /****f* LaTeX_Generator/Generate_LaTeX_Includes
442  * NAME
443  *   Generate_LaTeX_Includes -- generate include commands
444  * SYNOPSIS
445  *   void RB_Generate_LaTeX_Includes (FILE *dest)
446  * FUNCTION
447  *   Generates a series of \include commands to include the
448  *   documentation generated for each source file into one
449  *   big file.
450  ****
451  */
452
453 void RB_Generate_LaTeX_Includes(
454     FILE *dest )
455 {
456     USE( dest );
457     /* TODO  REMOVE ?? */
458 #if 0
459     struct RB_link     *cur_link;
460
461     for ( cur_link = first_link; cur_link; cur_link = cur_link->next_link )
462     {
463         {
464             if ( cur_link->type == NO_HEADER )
465                 fprintf( dest, "\\include{%s}\n", cur_link->label_name );
466         }
467     }
468 #endif
469 }
470
471
472
473 /****f* LaTeX_Generator/RB_LaTeX_Generate_Empty_Item
474  * NAME
475  *   RB_LaTeX_Generate_Empty_Item --
476  *****
477  */
478
479 void RB_LaTeX_Generate_Empty_Item(
480     FILE *dest_doc )
481 {
482     fprintf( dest_doc, "\\\\\n" );
483 }
484
485
486 /****f* LaTeX_Generator/RB_LaTeX_Generate_EscapedChar
487  * FUNCTION
488  *   Generate a single character.  These characters are outside
489  *   a begin{verbatim} end{verbatim} block. So we need to escape is
490  *   special characters.
491  *   These are
492  *       _  =>  \_
493  *       %  =>  \%
494  *       $  =>  \$
495  *       <  =>  \textless
496  *       >  =>  \textgreater
497  *       \  =>  $\backslash$
498  * SYNOPSIS
499  *   void RB_LaTeX_Generate_EscapedChar( FILE* dest_doc, int c )
500  * SEE ALSO
501  *   RB_LaTeX_Generate_Char()
502  *****
503  */
504
505 void RB_LaTeX_Generate_EscapedChar(
506     FILE *dest_doc,
507     int c )
508 {
509     switch ( c )
510     {
511     case '&':
512     case '~':
513     case '_':
514     case '%':
515     case '^':
516     case '{':
517     case '}':
518     case '$':
519     case '#':
520         fputc( '\\', dest_doc );
521         fputc( c, dest_doc );
522         break;
523 /* lowtexx 21.09.2005 11:12 */
524 /* Replace these characters by the correct latex-code */
525     case '\\':
526         fprintf( dest_doc, "$\\backslash$" );
527         break;
528     case '<':
529         fprintf( dest_doc, "\\textless " );
530         break;
531     case '>':
532         fprintf( dest_doc, "\\textgreater " );
533         break;
534 /* --- */
535     default:
536         fputc( c, dest_doc );
537         break;
538     }
539 }
540
541
542 /****f* LaTeX_Generator/RB_LaTeX_Generate_Char
543  * FUNCTION
544  *   Generate a single character.  These characters are generated
545  *   within a begin{verbatim} end{verbatim} block So no escaping is
546  *   necessary.
547  * SYNOPSIS
548  *   void RB_LaTeX_Generate_Char( FILE* dest_doc, int c )
549  *****
550  */
551
552 void RB_LaTeX_Generate_Char(
553     FILE *dest_doc,
554     int c )
555 {
556     if ( verbatim )
557     {
558         switch ( c )
559         {
560         case '\n':
561             assert( 0 );
562             break;
563         case '\t':
564             assert( 0 );
565             break;
566         default:
567             fputc( c, dest_doc );
568         }
569     }
570     else
571     {
572         RB_LaTeX_Generate_EscapedChar( dest_doc, c );
573     }
574 }
575
576
577 void LaTeX_Generate_Begin_Paragraph(
578     FILE *dest_doc )
579 {
580     fprintf( dest_doc, "\n" );
581 }
582
583 void LaTeX_Generate_End_Paragraph(
584     FILE *dest_doc )
585 {
586     fprintf( dest_doc, "\n" );
587 }
588
589
590 void LaTeX_Generate_Begin_Preformatted(
591     FILE *dest_doc )
592 {
593     fprintf( dest_doc, "\\begin{verbatim}\n" );
594     verbatim = TRUE;
595 }
596
597 void LaTeX_Generate_End_Preformatted(
598     FILE *dest_doc )
599 {
600     verbatim = FALSE;
601     fprintf( dest_doc, "\\end{verbatim}\n" );
602 }
603
604
605 void LaTeX_Generate_Begin_List(
606     FILE *dest_doc )
607 {
608     fprintf( dest_doc, "\\begin{itemize}\n" );
609 }
610
611 void LaTeX_Generate_End_List(
612     FILE *dest_doc )
613 {
614     fprintf( dest_doc, "\\end{itemize}\n" );
615 }
616
617 void LaTeX_Generate_Begin_List_Item(
618     FILE *dest_doc )
619 {
620     fprintf( dest_doc, "  \\item " );
621 }
622
623 void LaTeX_Generate_End_List_Item(
624     FILE *dest_doc )
625 {
626     USE( dest_doc );
627 //    fprintf( dest_doc, "" );
628 }
629
630
631
632 /* lowtexx 21.09.2005 11:23 */
633 /* added some functions to create links in latex documents */
634
635 /****f* LaTeX_Generator/RB_LaTeX_Generate_Label
636  * NAME
637  *   RB_LaTeX_Generate_Label --
638  * SYNOPSIS
639  *   void RB_LaTeX_Generate_Label( FILE* dest_doc, char* name)
640  * INPUTS
641  *   dest_doc  --  the file to which the text is written
642  *   name --  the unique name of the label to create
643  * SOURCE
644  */
645
646 void RB_LaTeX_Generate_Label(
647     FILE *dest_doc,
648     char *name )
649 {
650     int                 i;
651     int                 l = strlen( name );
652     unsigned char       c;
653
654     fprintf( dest_doc, "\\label{ch:" );
655     for ( i = 0; i < l; ++i )
656     {
657         c = name[i];
658         if ( utf8_isalnum( c ) )
659         {
660             RB_LaTeX_Generate_Char( dest_doc, c );
661         }
662         else
663         {
664             // think about this
665             // replaced by underscore
666             fputc( '_', dest_doc );
667         }
668     }
669     fprintf( dest_doc, "}\n" );
670 }
671
672 /******/
673
674
675 /****f* LaTeX_Generator/RB_LaTeX_Generate_Link
676  * NAME
677  *   RB_LaTeX_Generate_Link --
678  * SYNOPSIS
679  *   void RB_LaTeX_Generate_Link( FILE *cur_doc, char *cur_name,
680  *                                char *filename, char *labelname,
681  *                                char *linkname )
682  * INPUTS
683  *   cur_doc  --  the file to which the text is written
684  *   cur_name --  the name of the destination file (unused)
685  *                (the file from which we link)
686  *   filename --  the name of the file that contains the link
687  *                (the file we link to) (unused)
688  *   labelname--  the name of the unique label of the link.
689  *   linkname --  the name of the link as shown to the user (unused).
690  * SOURCE
691  */
692
693 void RB_LaTeX_Generate_Link(
694     FILE *cur_doc,
695     char *cur_name,
696     char *filename,
697     char *labelname,
698     char *linkname )
699 {
700     USE( cur_name );
701     USE( filename );
702     USE( linkname );
703
704     // Only generate links outside the verbatim sections
705     // LaTeX does not seem to recognise them inside (Thuffir)
706     if ( verbatim == FALSE )
707         fprintf( cur_doc, " (\\ref{ch:%s})", labelname );
708 }
709
710 /******/