freebsd-dev/contrib/texinfo/makeinfo/float.c
2005-05-23 10:46:22 +00:00

431 lines
13 KiB
C

/* float.c -- float environment functions.
$Id: float.c,v 1.8 2004/07/05 22:23:22 karl Exp $
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Originally written by Alper Ersoy <dirt@gtk.org>. */
#include "system.h"
#include "makeinfo.h"
#include "cmds.h"
#include "files.h"
#include "float.h"
#include "html.h"
#include "sectioning.h"
#include "xml.h"
static FLOAT_ELT *float_stack = NULL;
void
add_new_float (char *id, char *title, char *shorttitle,
char *type, char *position)
{
FLOAT_ELT *new = xmalloc (sizeof (FLOAT_ELT));
unsigned long num_len;
new->id = id;
new->type = type;
new->title = title;
new->shorttitle = shorttitle;
new->position = position;
new->title_used = 0;
new->defining_line = line_number - 1;
new->number = current_chapter_number ();
/* Append dot if not @unnumbered. */
num_len = strlen (new->number);
if (num_len > 0)
{
new->number = xrealloc (new->number, num_len + 1 + 1);
new->number[num_len] = '.';
new->number[num_len+1] = '\0';
}
{ /* Append the current float number. */
unsigned len = strlen (new->number) + 21; /* that's 64 bits */
char *s = xmalloc (len + 1);
sprintf (s, "%s%d", new->number,
count_floats_of_type_in_chapter (text_expansion (type),
new->number) + 1);
free (new->number);
new->number = xstrdup (s);
}
/* Plain text output needs sectioning number and its title,
when listing floats. */
if (!html && !xml && no_headers)
{
new->section = current_sectioning_number ();
if (strlen (new->section) == 0)
new->section_name = current_sectioning_name ();
else
new->section_name = "";
}
new->next = float_stack;
float_stack = new;
}
int
count_floats_of_type_in_chapter (char *type, char *chapter)
{
int i = 0;
int l = strlen (chapter);
FLOAT_ELT *temp = float_stack;
while (temp && strncmp (temp->number, chapter, l) == 0)
{
if (strlen (temp->id) > 0 && STREQ (text_expansion (temp->type), type))
i++;
temp = temp->next;
}
return i;
}
char *
current_float_title (void)
{
return float_stack->title;
}
char *
current_float_shorttitle (void)
{
return float_stack->shorttitle;
}
char *
current_float_type (void)
{
return float_stack->type;
}
char *
current_float_position (void)
{
return float_stack->position;
}
char *
current_float_number (void)
{
return float_stack->number;
}
char *
current_float_id (void)
{
return float_stack->id;
}
char *
get_float_ref (char *id)
{
FLOAT_ELT *temp = float_stack;
while (temp)
{
if (STREQ (id, temp->id))
{
char *s = xmalloc (strlen (temp->type) + strlen (temp->number) + 2);
sprintf (s, "%s %s", temp->type, temp->number);
return s;
}
temp = temp->next;
}
return NULL;
}
static int
float_type_exists (char *check_type)
{
/* Check if the requested float_type exists in the floats stack. */
FLOAT_ELT *temp;
for (temp = float_stack; temp; temp = temp->next)
if (STREQ (temp->type, check_type) && temp->id && *temp->id)
return 1;
return 0;
}
void
cm_listoffloats (void)
{
char *float_type;
get_rest_of_line (1, &float_type);
/* get_rest_of_line increments the line number by one,
so to make warnings/errors point to the correct line,
we decrement the line_number again. */
if (!handling_delayed_writes)
line_number--;
if (handling_delayed_writes && !float_type_exists (float_type))
warning (_("Requested float type `%s' not previously used"), float_type);
if (xml)
{
xml_insert_element_with_attribute (LISTOFFLOATS, START,
"type=\"%s\"", text_expansion (float_type));
xml_insert_element (LISTOFFLOATS, END);
}
else if (!handling_delayed_writes)
{
int command_len = sizeof ("@ ") + strlen (command) + strlen (float_type);
char *list_command = xmalloc (command_len + 1);
/* These are for the text following @listoffloats command.
Handling them with delayed writes is too late. */
close_paragraph ();
cm_noindent ();
sprintf (list_command, "@%s %s", command, float_type);
register_delayed_write (list_command);
free (list_command);
}
else if (float_type_exists (float_type))
{
FLOAT_ELT *temp = (FLOAT_ELT *) reverse_list
((GENERIC_LIST *) float_stack);
FLOAT_ELT *new_start = temp;
if (html)
insert_string ("<ul class=\"listoffloats\">\n");
else
{
if (!no_headers)
insert_string ("* Menu:\n\n");
}
while (temp)
{
if (strlen (temp->id) > 0 && STREQ (float_type, temp->type))
{
if (html)
{
/* A bit of space for HTML reabality. */
insert_string (" ");
add_html_block_elt ("<li>");
/* Simply relying on @ref command doesn't work here, because
commas in the caption may confuse the argument parsing. */
add_word ("<a href=\"");
add_anchor_name (temp->id, 1);
add_word ("\">");
if (strlen (float_type) > 0)
execute_string ("%s", float_type);
if (strlen (temp->id) > 0)
{
if (strlen (float_type) > 0)
add_char (' ');
add_word (temp->number);
}
if (strlen (temp->title) > 0)
{
if (strlen (float_type) > 0
|| strlen (temp->id) > 0)
insert_string (": ");
execute_string ("%s", temp->title);
}
add_word ("</a>");
add_html_block_elt ("</li>\n");
}
else
{
char *entry;
char *raw_entry;
char *title = expansion (temp->title, 0);
int len;
int aux_chars_len; /* these are asterisk, colon, etc. */
int column_width; /* width of the first column in menus. */
int number_len; /* length of Figure X.Y: etc. */
int i = 0;
/* Chosen widths are to match what @printindex produces. */
if (no_headers)
{
column_width = 43;
/* We have only one auxiliary character, NULL. */
aux_chars_len = sizeof ("");
}
else
{
column_width = 37;
/* We'll be adding an asterisk, followed by a space
and then a colon after the title, to construct a
proper menu item. */
aux_chars_len = sizeof ("* :");
}
/* Allocate enough space for possible expansion later. */
raw_entry = (char *) xmalloc (strlen (float_type)
+ strlen (temp->number) + strlen (title)
+ sizeof (": "));
sprintf (raw_entry, "%s %s", float_type, temp->number);
if (strlen (title) > 0)
strcat (raw_entry, ": ");
number_len = strlen (raw_entry);
len = strlen (title) + strlen (raw_entry);
/* If we have a @shortcaption, try it if @caption is
too long to fit on a line. */
if (len + aux_chars_len > column_width
&& strlen (temp->shorttitle) > 0)
title = expansion (temp->shorttitle, 0);
strcat (raw_entry, title);
len = strlen (raw_entry);
if (len + aux_chars_len > column_width)
{ /* Shorten long titles by looking for a space before
column_width - strlen (" ..."). */
/* -1 is for NULL, which is already in aux_chars_len. */
aux_chars_len += sizeof ("...") - 1;
len = column_width - aux_chars_len;
while (raw_entry[len] != ' ' && len >= 0)
len--;
/* Advance to the whitespace. */
len++;
/* If we are at the end of, say, Figure X.Y:, but
we have a title, then this means title does not
contain any whitespaces. Or it may be that we
went as far as the beginning. Just print as much
as possible of the title. */
if (len == 0
|| (len == number_len && strlen (title) > 0))
len = column_width - sizeof ("...");
/* Break here. */
raw_entry[len] = 0;
entry = xmalloc (len + aux_chars_len);
if (!no_headers)
strcpy (entry, "* ");
else
entry[0] = 0;
strcat (entry, raw_entry);
strcat (entry, "...");
if (!no_headers)
strcat (entry, ":");
}
else
{
entry = xmalloc (len + aux_chars_len);
if (!no_headers)
strcpy (entry, "* ");
else
entry[0] = 0;
strcat (entry, raw_entry);
if (!no_headers)
strcat (entry, ":");
}
insert_string (entry);
i = strlen (entry);
/* We insert space chars until ``column_width + four spaces''
is reached, to make the layout the same with what we produce
for @printindex. This is of course not obligatory, though
easier on the eye. -1 is for NULL. */
while (i < column_width + sizeof (" ") - 1)
{
insert (' ');
i++;
}
if (no_headers)
{
if (strlen (temp->section) > 0)
{ /* We got your number. */
insert_string ((char *) _("See "));
insert_string (temp->section);
}
else
{ /* Sigh, @float in an @unnumbered. :-\ */
insert_string ("\n ");
insert_string ((char *) _("See "));
insert_string ("``");
insert_string (expansion (temp->section_name, 0));
insert_string ("''");
}
}
else
insert_string (temp->id);
insert_string (".\n");
free (entry);
free (title);
}
}
temp = temp->next;
}
if (html)
{
inhibit_paragraph_indentation = 1;
insert_string ("</ul>\n\n");
}
else
insert ('\n');
/* Retain the original order of float stack. */
temp = new_start;
float_stack = (FLOAT_ELT *) reverse_list ((GENERIC_LIST *) temp);
}
free (float_type);
/* Re-increment the line number, because get_rest_of_line
left us looking at the next line after the command. */
line_number++;
}
int
current_float_used_title (void)
{
return float_stack->title_used;
}
void current_float_set_title_used (void)
{
float_stack->title_used = 1;
}