Merge from vendor branch OPENSSL:
[dragonfly.git] / contrib / texinfo-4 / makeinfo / float.c
1 /* float.c -- float environment functions.
2    $Id: float.c,v 1.8 2004/07/05 22:23:22 karl Exp $
3
4    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    Originally written by Alper Ersoy <dirt@gtk.org>.  */
21
22 #include "system.h"
23 #include "makeinfo.h"
24 #include "cmds.h"
25 #include "files.h"
26 #include "float.h"
27 #include "html.h"
28 #include "sectioning.h"
29 #include "xml.h"
30
31 static FLOAT_ELT *float_stack = NULL;
32
33 void
34 add_new_float (char *id, char *title, char *shorttitle,
35     char *type, char *position)
36 {
37   FLOAT_ELT *new = xmalloc (sizeof (FLOAT_ELT));
38   unsigned long num_len;
39
40   new->id = id;
41   new->type = type;
42   new->title = title;
43   new->shorttitle = shorttitle;
44   new->position = position;
45   new->title_used = 0;
46   new->defining_line = line_number - 1;
47
48   new->number = current_chapter_number ();
49   /* Append dot if not @unnumbered.  */
50   num_len = strlen (new->number);
51   if (num_len > 0)
52     {
53       new->number = xrealloc (new->number, num_len + 1 + 1);
54       new->number[num_len] = '.';
55       new->number[num_len+1] = '\0';
56     }
57
58   { /* Append the current float number.  */
59     unsigned len = strlen (new->number) + 21;  /* that's 64 bits */
60     char *s = xmalloc (len + 1);
61
62     sprintf (s, "%s%d", new->number,
63                 count_floats_of_type_in_chapter (text_expansion (type),
64                                                  new->number) + 1); 
65     free (new->number);
66     new->number = xstrdup (s);
67   }
68
69   /* Plain text output needs sectioning number and its title,
70      when listing floats.  */
71   if (!html && !xml && no_headers)
72     {
73       new->section = current_sectioning_number ();
74       if (strlen (new->section) == 0)
75         new->section_name = current_sectioning_name ();
76       else
77         new->section_name = "";
78     }
79
80   new->next = float_stack;
81   float_stack = new;
82 }
83
84 int
85 count_floats_of_type_in_chapter (char *type, char *chapter)
86 {
87   int i = 0;
88   int l = strlen (chapter);
89   FLOAT_ELT *temp = float_stack;
90
91   while (temp && strncmp (temp->number, chapter, l) == 0)
92     {
93       if (strlen (temp->id) > 0 && STREQ (text_expansion (temp->type), type))
94         i++;
95       temp = temp->next;
96     }
97
98   return i;
99 }
100
101 char *
102 current_float_title (void)
103 {
104   return float_stack->title;
105 }
106
107 char *
108 current_float_shorttitle (void)
109 {
110   return float_stack->shorttitle;
111 }
112
113 char *
114 current_float_type (void)
115 {
116   return float_stack->type;
117 }
118
119 char *
120 current_float_position (void)
121 {
122   return float_stack->position;
123 }
124
125 char *
126 current_float_number (void)
127 {
128   return float_stack->number;
129 }
130
131 char *
132 current_float_id (void)
133 {
134   return float_stack->id;
135 }
136
137 char *
138 get_float_ref (char *id)
139 {
140   FLOAT_ELT *temp = float_stack;
141
142   while (temp)
143     {
144       if (STREQ (id, temp->id))
145         {
146           char *s = xmalloc (strlen (temp->type) + strlen (temp->number) + 2);
147           sprintf (s, "%s %s", temp->type, temp->number);
148           return s;
149         }
150       temp = temp->next;
151     }
152
153   return NULL;
154 }
155
156 static int
157 float_type_exists (char *check_type)
158 {
159   /* Check if the requested float_type exists in the floats stack.  */
160   FLOAT_ELT *temp;
161
162   for (temp = float_stack; temp; temp = temp->next)
163     if (STREQ (temp->type, check_type) && temp->id && *temp->id)
164       return 1;
165
166   return 0;
167 }
168
169 void
170 cm_listoffloats (void)
171 {
172   char *float_type;
173   get_rest_of_line (1, &float_type);
174
175   /* get_rest_of_line increments the line number by one,
176      so to make warnings/errors point to the correct line,
177      we decrement the line_number again.  */
178   if (!handling_delayed_writes)
179     line_number--;
180
181   if (handling_delayed_writes && !float_type_exists (float_type))
182     warning (_("Requested float type `%s' not previously used"), float_type);
183
184   if (xml)
185     {
186       xml_insert_element_with_attribute (LISTOFFLOATS, START,
187           "type=\"%s\"", text_expansion (float_type));
188       xml_insert_element (LISTOFFLOATS, END);
189     }
190   else if (!handling_delayed_writes)
191     {
192       int command_len = sizeof ("@ ") + strlen (command) + strlen (float_type);
193       char *list_command = xmalloc (command_len + 1);
194
195       /* These are for the text following @listoffloats command.
196          Handling them with delayed writes is too late.  */
197       close_paragraph ();
198       cm_noindent ();
199
200       sprintf (list_command, "@%s %s", command, float_type);
201       register_delayed_write (list_command);
202       free (list_command);
203     }
204   else if (float_type_exists (float_type))
205     {
206       FLOAT_ELT *temp = (FLOAT_ELT *) reverse_list
207         ((GENERIC_LIST *) float_stack);
208       FLOAT_ELT *new_start = temp;
209
210       if (html)
211         insert_string ("<ul class=\"listoffloats\">\n");
212       else
213         {
214           if (!no_headers)
215             insert_string ("* Menu:\n\n");
216         }
217
218       while (temp)
219         {
220           if (strlen (temp->id) > 0 && STREQ (float_type, temp->type))
221             {
222               if (html)
223                 {
224                   /* A bit of space for HTML reabality.  */
225                   insert_string ("  ");
226                   add_html_block_elt ("<li>");
227
228                   /* Simply relying on @ref command doesn't work here, because
229                      commas in the caption may confuse the argument parsing.  */
230                   add_word ("<a href=\"");
231                   add_anchor_name (temp->id, 1);
232                   add_word ("\">");
233
234                   if (strlen (float_type) > 0)
235                     execute_string ("%s", float_type);
236
237                   if (strlen (temp->id) > 0)
238                     {
239                       if (strlen (float_type) > 0)
240                         add_char (' ');
241
242                       add_word (temp->number);
243                     }
244
245                   if (strlen (temp->title) > 0)
246                     {
247                       if (strlen (float_type) > 0
248                           || strlen (temp->id) > 0)
249                         insert_string (": ");
250
251                       execute_string ("%s", temp->title);
252                     }
253
254                   add_word ("</a>");
255
256                   add_html_block_elt ("</li>\n");
257                 }
258               else
259                 {
260                   char *entry;
261                   char *raw_entry;
262                   char *title = expansion (temp->title, 0);
263
264                   int len;
265                   int aux_chars_len; /* these are asterisk, colon, etc.  */
266                   int column_width; /* width of the first column in menus.  */
267                   int number_len; /* length of Figure X.Y: etc.   */
268                   int i = 0;
269
270                   /* Chosen widths are to match what @printindex produces.  */
271                   if (no_headers)
272                     {
273                       column_width = 43;
274                       /* We have only one auxiliary character, NULL.  */
275                       aux_chars_len = sizeof ("");
276                     }
277                   else
278                     {
279                       column_width = 37;
280                       /* We'll be adding an asterisk, followed by a space
281                          and then a colon after the title, to construct a
282                          proper menu item.  */
283                       aux_chars_len = sizeof ("* :");
284                     }
285
286                   /* Allocate enough space for possible expansion later.  */
287                   raw_entry = (char *) xmalloc (strlen (float_type)
288                       + strlen (temp->number) + strlen (title)
289                       + sizeof (":  "));
290
291                   sprintf (raw_entry, "%s %s", float_type, temp->number);
292
293                   if (strlen (title) > 0)
294                     strcat (raw_entry, ": ");
295
296                   number_len = strlen (raw_entry);
297
298                   len = strlen (title) + strlen (raw_entry);
299
300                   /* If we have a @shortcaption, try it if @caption is
301                      too long to fit on a line.  */
302                   if (len + aux_chars_len > column_width
303                       && strlen (temp->shorttitle) > 0)
304                     title = expansion (temp->shorttitle, 0);
305
306                   strcat (raw_entry, title);
307                   len = strlen (raw_entry);
308
309                   if (len + aux_chars_len > column_width)
310                     { /* Shorten long titles by looking for a space before
311                          column_width - strlen (" ...").  */
312                       /* -1 is for NULL, which is already in aux_chars_len.  */
313                       aux_chars_len += sizeof ("...") - 1;
314                       len = column_width - aux_chars_len;
315                       while (raw_entry[len] != ' ' && len >= 0)
316                         len--;
317
318                       /* Advance to the whitespace.  */
319                       len++;
320
321                       /* If we are at the end of, say, Figure X.Y:, but
322                          we have a title, then this means title does not
323                          contain any whitespaces.  Or it may be that we
324                          went as far as the beginning.  Just print as much
325                          as possible of the title.  */
326                       if (len == 0
327                           || (len == number_len && strlen (title) > 0))
328                         len = column_width - sizeof ("...");
329
330                       /* Break here.  */
331                       raw_entry[len] = 0;
332
333                       entry = xmalloc (len + aux_chars_len);
334
335                       if (!no_headers)
336                         strcpy (entry, "* ");
337                       else
338                         entry[0] = 0;
339
340                       strcat (entry, raw_entry);
341                       strcat (entry, "...");
342
343                       if (!no_headers)
344                         strcat (entry, ":");
345                     }
346                   else
347                     {
348                       entry = xmalloc (len + aux_chars_len);
349
350                       if (!no_headers)
351                         strcpy (entry, "* ");
352                       else
353                         entry[0] = 0;
354
355                       strcat (entry, raw_entry);
356
357                       if (!no_headers)
358                         strcat (entry, ":");
359                     }
360
361                   insert_string (entry);
362
363                   i = strlen (entry);
364                   /* We insert space chars until ``column_width + four spaces''
365                      is reached, to make the layout the same with what we produce
366                      for @printindex.  This is of course not obligatory, though
367                      easier on the eye.  -1 is for NULL.  */
368                   while (i < column_width + sizeof ("    ") - 1)
369                     {
370                       insert (' ');
371                       i++;
372                     }
373
374                   if (no_headers)
375                     {
376                       if (strlen (temp->section) > 0)
377                         { /* We got your number.  */
378                           insert_string ((char *) _("See "));
379                           insert_string (temp->section);
380                         }
381                       else
382                         { /* Sigh, @float in an @unnumbered. :-\  */
383                           insert_string ("\n          ");
384                           insert_string ((char *) _("See "));
385                           insert_string ("``");
386                           insert_string (expansion (temp->section_name, 0));
387                           insert_string ("''");
388                         }
389                     }
390                   else
391                     insert_string (temp->id);
392
393                   insert_string (".\n");
394
395                   free (entry);
396                   free (title);
397                 }
398             }
399           temp = temp->next;
400         }
401
402       if (html)
403         {
404           inhibit_paragraph_indentation = 1;
405           insert_string ("</ul>\n\n");
406         }
407       else
408         insert ('\n');
409
410       /* Retain the original order of float stack.  */
411       temp = new_start;
412       float_stack = (FLOAT_ELT *) reverse_list ((GENERIC_LIST *) temp);
413     }
414
415   free (float_type);
416   /* Re-increment the line number, because get_rest_of_line
417      left us looking at the next line after the command.  */
418   line_number++;
419 }
420
421 int
422 current_float_used_title (void)
423 {
424         return float_stack->title_used;
425 }
426
427 void current_float_set_title_used (void)
428 {
429         float_stack->title_used = 1;
430 }