Back to index

tetex-bin  3.0
float.c
Go to the documentation of this file.
00001 /* float.c -- float environment functions.
00002    $Id: float.c,v 1.8 2004/07/05 22:23:22 karl Exp $
00003 
00004    Copyright (C) 2003, 2004 Free Software Foundation, Inc.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2, or (at your option)
00009    any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 
00020    Originally written by Alper Ersoy <dirt@gtk.org>.  */
00021 
00022 #include "system.h"
00023 #include "makeinfo.h"
00024 #include "cmds.h"
00025 #include "files.h"
00026 #include "float.h"
00027 #include "html.h"
00028 #include "sectioning.h"
00029 #include "xml.h"
00030 
00031 static FLOAT_ELT *float_stack = NULL;
00032 
00033 void
00034 add_new_float (char *id, char *title, char *shorttitle,
00035     char *type, char *position)
00036 {
00037   FLOAT_ELT *new = xmalloc (sizeof (FLOAT_ELT));
00038   unsigned long num_len;
00039 
00040   new->id = id;
00041   new->type = type;
00042   new->title = title;
00043   new->shorttitle = shorttitle;
00044   new->position = position;
00045   new->title_used = 0;
00046   new->defining_line = line_number - 1;
00047 
00048   new->number = current_chapter_number ();
00049   /* Append dot if not @unnumbered.  */
00050   num_len = strlen (new->number);
00051   if (num_len > 0)
00052     {
00053       new->number = xrealloc (new->number, num_len + 1 + 1);
00054       new->number[num_len] = '.';
00055       new->number[num_len+1] = '\0';
00056     }
00057 
00058   { /* Append the current float number.  */
00059     unsigned len = strlen (new->number) + 21;  /* that's 64 bits */
00060     char *s = xmalloc (len + 1);
00061 
00062     sprintf (s, "%s%d", new->number,
00063                 count_floats_of_type_in_chapter (text_expansion (type),
00064                                                  new->number) + 1); 
00065     free (new->number);
00066     new->number = xstrdup (s);
00067   }
00068 
00069   /* Plain text output needs sectioning number and its title,
00070      when listing floats.  */
00071   if (!html && !xml && no_headers)
00072     {
00073       new->section = current_sectioning_number ();
00074       if (strlen (new->section) == 0)
00075         new->section_name = current_sectioning_name ();
00076       else
00077         new->section_name = "";
00078     }
00079 
00080   new->next = float_stack;
00081   float_stack = new;
00082 }
00083 
00084 int
00085 count_floats_of_type_in_chapter (char *type, char *chapter)
00086 {
00087   int i = 0;
00088   int l = strlen (chapter);
00089   FLOAT_ELT *temp = float_stack;
00090 
00091   while (temp && strncmp (temp->number, chapter, l) == 0)
00092     {
00093       if (strlen (temp->id) > 0 && STREQ (text_expansion (temp->type), type))
00094         i++;
00095       temp = temp->next;
00096     }
00097 
00098   return i;
00099 }
00100 
00101 char *
00102 current_float_title (void)
00103 {
00104   return float_stack->title;
00105 }
00106 
00107 char *
00108 current_float_shorttitle (void)
00109 {
00110   return float_stack->shorttitle;
00111 }
00112 
00113 char *
00114 current_float_type (void)
00115 {
00116   return float_stack->type;
00117 }
00118 
00119 char *
00120 current_float_position (void)
00121 {
00122   return float_stack->position;
00123 }
00124 
00125 char *
00126 current_float_number (void)
00127 {
00128   return float_stack->number;
00129 }
00130 
00131 char *
00132 current_float_id (void)
00133 {
00134   return float_stack->id;
00135 }
00136 
00137 char *
00138 get_float_ref (char *id)
00139 {
00140   FLOAT_ELT *temp = float_stack;
00141 
00142   while (temp)
00143     {
00144       if (STREQ (id, temp->id))
00145         {
00146           char *s = xmalloc (strlen (temp->type) + strlen (temp->number) + 2);
00147           sprintf (s, "%s %s", temp->type, temp->number);
00148           return s;
00149         }
00150       temp = temp->next;
00151     }
00152 
00153   return NULL;
00154 }
00155 
00156 static int
00157 float_type_exists (char *check_type)
00158 {
00159   /* Check if the requested float_type exists in the floats stack.  */
00160   FLOAT_ELT *temp;
00161 
00162   for (temp = float_stack; temp; temp = temp->next)
00163     if (STREQ (temp->type, check_type) && temp->id && *temp->id)
00164       return 1;
00165 
00166   return 0;
00167 }
00168 
00169 void
00170 cm_listoffloats (void)
00171 {
00172   char *float_type;
00173   get_rest_of_line (1, &float_type);
00174 
00175   /* get_rest_of_line increments the line number by one,
00176      so to make warnings/errors point to the correct line,
00177      we decrement the line_number again.  */
00178   if (!handling_delayed_writes)
00179     line_number--;
00180 
00181   if (handling_delayed_writes && !float_type_exists (float_type))
00182     warning (_("Requested float type `%s' not previously used"), float_type);
00183 
00184   if (xml)
00185     {
00186       xml_insert_element_with_attribute (LISTOFFLOATS, START,
00187           "type=\"%s\"", text_expansion (float_type));
00188       xml_insert_element (LISTOFFLOATS, END);
00189     }
00190   else if (!handling_delayed_writes)
00191     {
00192       int command_len = sizeof ("@ ") + strlen (command) + strlen (float_type);
00193       char *list_command = xmalloc (command_len + 1);
00194 
00195       /* These are for the text following @listoffloats command.
00196          Handling them with delayed writes is too late.  */
00197       close_paragraph ();
00198       cm_noindent ();
00199 
00200       sprintf (list_command, "@%s %s", command, float_type);
00201       register_delayed_write (list_command);
00202       free (list_command);
00203     }
00204   else if (float_type_exists (float_type))
00205     {
00206       FLOAT_ELT *temp = (FLOAT_ELT *) reverse_list
00207         ((GENERIC_LIST *) float_stack);
00208       FLOAT_ELT *new_start = temp;
00209 
00210       if (html)
00211         insert_string ("<ul class=\"listoffloats\">\n");
00212       else
00213         {
00214           if (!no_headers)
00215             insert_string ("* Menu:\n\n");
00216         }
00217 
00218       while (temp)
00219         {
00220           if (strlen (temp->id) > 0 && STREQ (float_type, temp->type))
00221             {
00222               if (html)
00223                 {
00224                   /* A bit of space for HTML reabality.  */
00225                   insert_string ("  ");
00226                   add_html_block_elt ("<li>");
00227 
00228                   /* Simply relying on @ref command doesn't work here, because
00229                      commas in the caption may confuse the argument parsing.  */
00230                   add_word ("<a href=\"");
00231                   add_anchor_name (temp->id, 1);
00232                   add_word ("\">");
00233 
00234                   if (strlen (float_type) > 0)
00235                     execute_string ("%s", float_type);
00236 
00237                   if (strlen (temp->id) > 0)
00238                     {
00239                       if (strlen (float_type) > 0)
00240                         add_char (' ');
00241 
00242                       add_word (temp->number);
00243                     }
00244 
00245                   if (strlen (temp->title) > 0)
00246                     {
00247                       if (strlen (float_type) > 0
00248                           || strlen (temp->id) > 0)
00249                         insert_string (": ");
00250 
00251                       execute_string ("%s", temp->title);
00252                     }
00253 
00254                   add_word ("</a>");
00255 
00256                   add_html_block_elt ("</li>\n");
00257                 }
00258               else
00259                 {
00260                   char *entry;
00261                   char *raw_entry;
00262                   char *title = expansion (temp->title, 0);
00263 
00264                   int len;
00265                   int aux_chars_len; /* these are asterisk, colon, etc.  */
00266                   int column_width; /* width of the first column in menus.  */
00267                   int number_len; /* length of Figure X.Y: etc.   */
00268                   int i = 0;
00269 
00270                   /* Chosen widths are to match what @printindex produces.  */
00271                   if (no_headers)
00272                     {
00273                       column_width = 43;
00274                       /* We have only one auxiliary character, NULL.  */
00275                       aux_chars_len = sizeof ("");
00276                     }
00277                   else
00278                     {
00279                       column_width = 37;
00280                       /* We'll be adding an asterisk, followed by a space
00281                          and then a colon after the title, to construct a
00282                          proper menu item.  */
00283                       aux_chars_len = sizeof ("* :");
00284                     }
00285 
00286                   /* Allocate enough space for possible expansion later.  */
00287                   raw_entry = (char *) xmalloc (strlen (float_type)
00288                       + strlen (temp->number) + strlen (title)
00289                       + sizeof (":  "));
00290 
00291                   sprintf (raw_entry, "%s %s", float_type, temp->number);
00292 
00293                   if (strlen (title) > 0)
00294                     strcat (raw_entry, ": ");
00295 
00296                   number_len = strlen (raw_entry);
00297 
00298                   len = strlen (title) + strlen (raw_entry);
00299 
00300                   /* If we have a @shortcaption, try it if @caption is
00301                      too long to fit on a line.  */
00302                   if (len + aux_chars_len > column_width
00303                       && strlen (temp->shorttitle) > 0)
00304                     title = expansion (temp->shorttitle, 0);
00305 
00306                   strcat (raw_entry, title);
00307                   len = strlen (raw_entry);
00308 
00309                   if (len + aux_chars_len > column_width)
00310                     { /* Shorten long titles by looking for a space before
00311                          column_width - strlen (" ...").  */
00312                       /* -1 is for NULL, which is already in aux_chars_len.  */
00313                       aux_chars_len += sizeof ("...") - 1;
00314                       len = column_width - aux_chars_len;
00315                       while (raw_entry[len] != ' ' && len >= 0)
00316                         len--;
00317 
00318                       /* Advance to the whitespace.  */
00319                       len++;
00320 
00321                       /* If we are at the end of, say, Figure X.Y:, but
00322                          we have a title, then this means title does not
00323                          contain any whitespaces.  Or it may be that we
00324                          went as far as the beginning.  Just print as much
00325                          as possible of the title.  */
00326                       if (len == 0
00327                           || (len == number_len && strlen (title) > 0))
00328                         len = column_width - sizeof ("...");
00329 
00330                       /* Break here.  */
00331                       raw_entry[len] = 0;
00332 
00333                       entry = xmalloc (len + aux_chars_len);
00334 
00335                       if (!no_headers)
00336                         strcpy (entry, "* ");
00337                       else
00338                         entry[0] = 0;
00339 
00340                       strcat (entry, raw_entry);
00341                       strcat (entry, "...");
00342 
00343                       if (!no_headers)
00344                         strcat (entry, ":");
00345                     }
00346                   else
00347                     {
00348                       entry = xmalloc (len + aux_chars_len);
00349 
00350                       if (!no_headers)
00351                         strcpy (entry, "* ");
00352                       else
00353                         entry[0] = 0;
00354 
00355                       strcat (entry, raw_entry);
00356 
00357                       if (!no_headers)
00358                         strcat (entry, ":");
00359                     }
00360 
00361                   insert_string (entry);
00362 
00363                   i = strlen (entry);
00364                   /* We insert space chars until ``column_width + four spaces''
00365                      is reached, to make the layout the same with what we produce
00366                      for @printindex.  This is of course not obligatory, though
00367                      easier on the eye.  -1 is for NULL.  */
00368                   while (i < column_width + sizeof ("    ") - 1)
00369                     {
00370                       insert (' ');
00371                       i++;
00372                     }
00373 
00374                   if (no_headers)
00375                     {
00376                       if (strlen (temp->section) > 0)
00377                         { /* We got your number.  */
00378                           insert_string ((char *) _("See "));
00379                           insert_string (temp->section);
00380                         }
00381                       else
00382                         { /* Sigh, @float in an @unnumbered. :-\  */
00383                           insert_string ("\n          ");
00384                           insert_string ((char *) _("See "));
00385                           insert_string ("``");
00386                           insert_string (expansion (temp->section_name, 0));
00387                           insert_string ("''");
00388                         }
00389                     }
00390                   else
00391                     insert_string (temp->id);
00392 
00393                   insert_string (".\n");
00394 
00395                   free (entry);
00396                   free (title);
00397                 }
00398             }
00399           temp = temp->next;
00400         }
00401 
00402       if (html)
00403         {
00404           inhibit_paragraph_indentation = 1;
00405           insert_string ("</ul>\n\n");
00406         }
00407       else
00408         insert ('\n');
00409 
00410       /* Retain the original order of float stack.  */
00411       temp = new_start;
00412       float_stack = (FLOAT_ELT *) reverse_list ((GENERIC_LIST *) temp);
00413     }
00414 
00415   free (float_type);
00416   /* Re-increment the line number, because get_rest_of_line
00417      left us looking at the next line after the command.  */
00418   line_number++;
00419 }
00420 
00421 int
00422 current_float_used_title (void)
00423 {
00424        return float_stack->title_used;
00425 }
00426 
00427 void current_float_set_title_used (void)
00428 {
00429        float_stack->title_used = 1;
00430 }