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