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
33static FLOAT_ELT *float_stack = NULL;
34
35void
36add_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
86int
87count_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
103char *
104current_float_title (void)
105{
106  return float_stack->title;
107}
108
109char *
110current_float_shorttitle (void)
111{
112  return float_stack->shorttitle;
113}
114
115char *
116current_float_type (void)
117{
118  return float_stack->type;
119}
120
121char *
122current_float_position (void)
123{
124  return float_stack->position;
125}
126
127char *
128current_float_number (void)
129{
130  return float_stack->number;
131}
132
133char *
134current_float_id (void)
135{
136  return float_stack->id;
137}
138
139char *
140get_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
158static int
159float_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
171void
172cm_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
423int
424current_float_used_title (void)
425{
426	return float_stack->title_used;
427}
428
429void current_float_set_title_used (void)
430{
431	float_stack->title_used = 1;
432}
433