1146515Sru/* float.c -- float environment functions. 2146515Sru $Id: float.c,v 1.8 2004/07/05 22:23:22 karl Exp $ 3146515Sru 4146515Sru Copyright (C) 2003, 2004 Free Software Foundation, Inc. 5146515Sru 6146515Sru This program is free software; you can redistribute it and/or modify 7146515Sru it under the terms of the GNU General Public License as published by 8146515Sru the Free Software Foundation; either version 2, or (at your option) 9146515Sru any later version. 10146515Sru 11146515Sru This program is distributed in the hope that it will be useful, 12146515Sru but WITHOUT ANY WARRANTY; without even the implied warranty of 13146515Sru MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14146515Sru GNU General Public License for more details. 15146515Sru 16146515Sru You should have received a copy of the GNU General Public License 17146515Sru along with this program; if not, write to the Free Software 18146515Sru Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19146515Sru 20146515Sru Originally written by Alper Ersoy <dirt@gtk.org>. */ 21146515Sru 22146515Sru#include "system.h" 23146515Sru#include "makeinfo.h" 24146515Sru#include "cmds.h" 25146515Sru#include "files.h" 26146515Sru#include "float.h" 27146515Sru#include "html.h" 28146515Sru#include "sectioning.h" 29146515Sru#include "xml.h" 30146515Sru 31146515Srustatic FLOAT_ELT *float_stack = NULL; 32146515Sru 33146515Sruvoid 34146515Sruadd_new_float (char *id, char *title, char *shorttitle, 35146515Sru char *type, char *position) 36146515Sru{ 37146515Sru FLOAT_ELT *new = xmalloc (sizeof (FLOAT_ELT)); 38146515Sru unsigned long num_len; 39146515Sru 40146515Sru new->id = id; 41146515Sru new->type = type; 42146515Sru new->title = title; 43146515Sru new->shorttitle = shorttitle; 44146515Sru new->position = position; 45146515Sru new->title_used = 0; 46146515Sru new->defining_line = line_number - 1; 47146515Sru 48146515Sru new->number = current_chapter_number (); 49146515Sru /* Append dot if not @unnumbered. */ 50146515Sru num_len = strlen (new->number); 51146515Sru if (num_len > 0) 52146515Sru { 53146515Sru new->number = xrealloc (new->number, num_len + 1 + 1); 54146515Sru new->number[num_len] = '.'; 55146515Sru new->number[num_len+1] = '\0'; 56146515Sru } 57146515Sru 58146515Sru { /* Append the current float number. */ 59146515Sru unsigned len = strlen (new->number) + 21; /* that's 64 bits */ 60146515Sru char *s = xmalloc (len + 1); 61146515Sru 62146515Sru sprintf (s, "%s%d", new->number, 63146515Sru count_floats_of_type_in_chapter (text_expansion (type), 64146515Sru new->number) + 1); 65146515Sru free (new->number); 66146515Sru new->number = xstrdup (s); 67146515Sru } 68146515Sru 69146515Sru /* Plain text output needs sectioning number and its title, 70146515Sru when listing floats. */ 71146515Sru if (!html && !xml && no_headers) 72146515Sru { 73146515Sru new->section = current_sectioning_number (); 74146515Sru if (strlen (new->section) == 0) 75146515Sru new->section_name = current_sectioning_name (); 76146515Sru else 77146515Sru new->section_name = ""; 78146515Sru } 79146515Sru 80146515Sru new->next = float_stack; 81146515Sru float_stack = new; 82146515Sru} 83146515Sru 84146515Sruint 85146515Srucount_floats_of_type_in_chapter (char *type, char *chapter) 86146515Sru{ 87146515Sru int i = 0; 88146515Sru int l = strlen (chapter); 89146515Sru FLOAT_ELT *temp = float_stack; 90146515Sru 91146515Sru while (temp && strncmp (temp->number, chapter, l) == 0) 92146515Sru { 93146515Sru if (strlen (temp->id) > 0 && STREQ (text_expansion (temp->type), type)) 94146515Sru i++; 95146515Sru temp = temp->next; 96146515Sru } 97146515Sru 98146515Sru return i; 99146515Sru} 100146515Sru 101146515Sruchar * 102146515Srucurrent_float_title (void) 103146515Sru{ 104146515Sru return float_stack->title; 105146515Sru} 106146515Sru 107146515Sruchar * 108146515Srucurrent_float_shorttitle (void) 109146515Sru{ 110146515Sru return float_stack->shorttitle; 111146515Sru} 112146515Sru 113146515Sruchar * 114146515Srucurrent_float_type (void) 115146515Sru{ 116146515Sru return float_stack->type; 117146515Sru} 118146515Sru 119146515Sruchar * 120146515Srucurrent_float_position (void) 121146515Sru{ 122146515Sru return float_stack->position; 123146515Sru} 124146515Sru 125146515Sruchar * 126146515Srucurrent_float_number (void) 127146515Sru{ 128146515Sru return float_stack->number; 129146515Sru} 130146515Sru 131146515Sruchar * 132146515Srucurrent_float_id (void) 133146515Sru{ 134146515Sru return float_stack->id; 135146515Sru} 136146515Sru 137146515Sruchar * 138146515Sruget_float_ref (char *id) 139146515Sru{ 140146515Sru FLOAT_ELT *temp = float_stack; 141146515Sru 142146515Sru while (temp) 143146515Sru { 144146515Sru if (STREQ (id, temp->id)) 145146515Sru { 146146515Sru char *s = xmalloc (strlen (temp->type) + strlen (temp->number) + 2); 147146515Sru sprintf (s, "%s %s", temp->type, temp->number); 148146515Sru return s; 149146515Sru } 150146515Sru temp = temp->next; 151146515Sru } 152146515Sru 153146515Sru return NULL; 154146515Sru} 155146515Sru 156146515Srustatic int 157146515Srufloat_type_exists (char *check_type) 158146515Sru{ 159146515Sru /* Check if the requested float_type exists in the floats stack. */ 160146515Sru FLOAT_ELT *temp; 161146515Sru 162146515Sru for (temp = float_stack; temp; temp = temp->next) 163146515Sru if (STREQ (temp->type, check_type) && temp->id && *temp->id) 164146515Sru return 1; 165146515Sru 166146515Sru return 0; 167146515Sru} 168146515Sru 169146515Sruvoid 170146515Srucm_listoffloats (void) 171146515Sru{ 172146515Sru char *float_type; 173146515Sru get_rest_of_line (1, &float_type); 174146515Sru 175146515Sru /* get_rest_of_line increments the line number by one, 176146515Sru so to make warnings/errors point to the correct line, 177146515Sru we decrement the line_number again. */ 178146515Sru if (!handling_delayed_writes) 179146515Sru line_number--; 180146515Sru 181146515Sru if (handling_delayed_writes && !float_type_exists (float_type)) 182146515Sru warning (_("Requested float type `%s' not previously used"), float_type); 183146515Sru 184146515Sru if (xml) 185146515Sru { 186146515Sru xml_insert_element_with_attribute (LISTOFFLOATS, START, 187146515Sru "type=\"%s\"", text_expansion (float_type)); 188146515Sru xml_insert_element (LISTOFFLOATS, END); 189146515Sru } 190146515Sru else if (!handling_delayed_writes) 191146515Sru { 192146515Sru int command_len = sizeof ("@ ") + strlen (command) + strlen (float_type); 193146515Sru char *list_command = xmalloc (command_len + 1); 194146515Sru 195146515Sru /* These are for the text following @listoffloats command. 196146515Sru Handling them with delayed writes is too late. */ 197146515Sru close_paragraph (); 198146515Sru cm_noindent (); 199146515Sru 200146515Sru sprintf (list_command, "@%s %s", command, float_type); 201146515Sru register_delayed_write (list_command); 202146515Sru free (list_command); 203146515Sru } 204146515Sru else if (float_type_exists (float_type)) 205146515Sru { 206146515Sru FLOAT_ELT *temp = (FLOAT_ELT *) reverse_list 207146515Sru ((GENERIC_LIST *) float_stack); 208146515Sru FLOAT_ELT *new_start = temp; 209146515Sru 210146515Sru if (html) 211146515Sru insert_string ("<ul class=\"listoffloats\">\n"); 212146515Sru else 213146515Sru { 214146515Sru if (!no_headers) 215146515Sru insert_string ("* Menu:\n\n"); 216146515Sru } 217146515Sru 218146515Sru while (temp) 219146515Sru { 220146515Sru if (strlen (temp->id) > 0 && STREQ (float_type, temp->type)) 221146515Sru { 222146515Sru if (html) 223146515Sru { 224146515Sru /* A bit of space for HTML reabality. */ 225146515Sru insert_string (" "); 226146515Sru add_html_block_elt ("<li>"); 227146515Sru 228146515Sru /* Simply relying on @ref command doesn't work here, because 229146515Sru commas in the caption may confuse the argument parsing. */ 230146515Sru add_word ("<a href=\""); 231146515Sru add_anchor_name (temp->id, 1); 232146515Sru add_word ("\">"); 233146515Sru 234146515Sru if (strlen (float_type) > 0) 235146515Sru execute_string ("%s", float_type); 236146515Sru 237146515Sru if (strlen (temp->id) > 0) 238146515Sru { 239146515Sru if (strlen (float_type) > 0) 240146515Sru add_char (' '); 241146515Sru 242146515Sru add_word (temp->number); 243146515Sru } 244146515Sru 245146515Sru if (strlen (temp->title) > 0) 246146515Sru { 247146515Sru if (strlen (float_type) > 0 248146515Sru || strlen (temp->id) > 0) 249146515Sru insert_string (": "); 250146515Sru 251146515Sru execute_string ("%s", temp->title); 252146515Sru } 253146515Sru 254146515Sru add_word ("</a>"); 255146515Sru 256146515Sru add_html_block_elt ("</li>\n"); 257146515Sru } 258146515Sru else 259146515Sru { 260146515Sru char *entry; 261146515Sru char *raw_entry; 262146515Sru char *title = expansion (temp->title, 0); 263146515Sru 264146515Sru int len; 265146515Sru int aux_chars_len; /* these are asterisk, colon, etc. */ 266146515Sru int column_width; /* width of the first column in menus. */ 267146515Sru int number_len; /* length of Figure X.Y: etc. */ 268146515Sru int i = 0; 269146515Sru 270146515Sru /* Chosen widths are to match what @printindex produces. */ 271146515Sru if (no_headers) 272146515Sru { 273146515Sru column_width = 43; 274146515Sru /* We have only one auxiliary character, NULL. */ 275146515Sru aux_chars_len = sizeof (""); 276146515Sru } 277146515Sru else 278146515Sru { 279146515Sru column_width = 37; 280146515Sru /* We'll be adding an asterisk, followed by a space 281146515Sru and then a colon after the title, to construct a 282146515Sru proper menu item. */ 283146515Sru aux_chars_len = sizeof ("* :"); 284146515Sru } 285146515Sru 286146515Sru /* Allocate enough space for possible expansion later. */ 287146515Sru raw_entry = (char *) xmalloc (strlen (float_type) 288146515Sru + strlen (temp->number) + strlen (title) 289146515Sru + sizeof (": ")); 290146515Sru 291146515Sru sprintf (raw_entry, "%s %s", float_type, temp->number); 292146515Sru 293146515Sru if (strlen (title) > 0) 294146515Sru strcat (raw_entry, ": "); 295146515Sru 296146515Sru number_len = strlen (raw_entry); 297146515Sru 298146515Sru len = strlen (title) + strlen (raw_entry); 299146515Sru 300146515Sru /* If we have a @shortcaption, try it if @caption is 301146515Sru too long to fit on a line. */ 302146515Sru if (len + aux_chars_len > column_width 303146515Sru && strlen (temp->shorttitle) > 0) 304146515Sru title = expansion (temp->shorttitle, 0); 305146515Sru 306146515Sru strcat (raw_entry, title); 307146515Sru len = strlen (raw_entry); 308146515Sru 309146515Sru if (len + aux_chars_len > column_width) 310146515Sru { /* Shorten long titles by looking for a space before 311146515Sru column_width - strlen (" ..."). */ 312146515Sru /* -1 is for NULL, which is already in aux_chars_len. */ 313146515Sru aux_chars_len += sizeof ("...") - 1; 314146515Sru len = column_width - aux_chars_len; 315146515Sru while (raw_entry[len] != ' ' && len >= 0) 316146515Sru len--; 317146515Sru 318146515Sru /* Advance to the whitespace. */ 319146515Sru len++; 320146515Sru 321146515Sru /* If we are at the end of, say, Figure X.Y:, but 322146515Sru we have a title, then this means title does not 323146515Sru contain any whitespaces. Or it may be that we 324146515Sru went as far as the beginning. Just print as much 325146515Sru as possible of the title. */ 326146515Sru if (len == 0 327146515Sru || (len == number_len && strlen (title) > 0)) 328146515Sru len = column_width - sizeof ("..."); 329146515Sru 330146515Sru /* Break here. */ 331146515Sru raw_entry[len] = 0; 332146515Sru 333146515Sru entry = xmalloc (len + aux_chars_len); 334146515Sru 335146515Sru if (!no_headers) 336146515Sru strcpy (entry, "* "); 337146515Sru else 338146515Sru entry[0] = 0; 339146515Sru 340146515Sru strcat (entry, raw_entry); 341146515Sru strcat (entry, "..."); 342146515Sru 343146515Sru if (!no_headers) 344146515Sru strcat (entry, ":"); 345146515Sru } 346146515Sru else 347146515Sru { 348146515Sru entry = xmalloc (len + aux_chars_len); 349146515Sru 350146515Sru if (!no_headers) 351146515Sru strcpy (entry, "* "); 352146515Sru else 353146515Sru entry[0] = 0; 354146515Sru 355146515Sru strcat (entry, raw_entry); 356146515Sru 357146515Sru if (!no_headers) 358146515Sru strcat (entry, ":"); 359146515Sru } 360146515Sru 361146515Sru insert_string (entry); 362146515Sru 363146515Sru i = strlen (entry); 364146515Sru /* We insert space chars until ``column_width + four spaces'' 365146515Sru is reached, to make the layout the same with what we produce 366146515Sru for @printindex. This is of course not obligatory, though 367146515Sru easier on the eye. -1 is for NULL. */ 368146515Sru while (i < column_width + sizeof (" ") - 1) 369146515Sru { 370146515Sru insert (' '); 371146515Sru i++; 372146515Sru } 373146515Sru 374146515Sru if (no_headers) 375146515Sru { 376146515Sru if (strlen (temp->section) > 0) 377146515Sru { /* We got your number. */ 378146515Sru insert_string ((char *) _("See ")); 379146515Sru insert_string (temp->section); 380146515Sru } 381146515Sru else 382146515Sru { /* Sigh, @float in an @unnumbered. :-\ */ 383146515Sru insert_string ("\n "); 384146515Sru insert_string ((char *) _("See ")); 385146515Sru insert_string ("``"); 386146515Sru insert_string (expansion (temp->section_name, 0)); 387146515Sru insert_string ("''"); 388146515Sru } 389146515Sru } 390146515Sru else 391146515Sru insert_string (temp->id); 392146515Sru 393146515Sru insert_string (".\n"); 394146515Sru 395146515Sru free (entry); 396146515Sru free (title); 397146515Sru } 398146515Sru } 399146515Sru temp = temp->next; 400146515Sru } 401146515Sru 402146515Sru if (html) 403146515Sru { 404146515Sru inhibit_paragraph_indentation = 1; 405146515Sru insert_string ("</ul>\n\n"); 406146515Sru } 407146515Sru else 408146515Sru insert ('\n'); 409146515Sru 410146515Sru /* Retain the original order of float stack. */ 411146515Sru temp = new_start; 412146515Sru float_stack = (FLOAT_ELT *) reverse_list ((GENERIC_LIST *) temp); 413146515Sru } 414146515Sru 415146515Sru free (float_type); 416146515Sru /* Re-increment the line number, because get_rest_of_line 417146515Sru left us looking at the next line after the command. */ 418146515Sru line_number++; 419146515Sru} 420146515Sru 421146515Sruint 422146515Srucurrent_float_used_title (void) 423146515Sru{ 424146515Sru return float_stack->title_used; 425146515Sru} 426146515Sru 427146515Sruvoid current_float_set_title_used (void) 428146515Sru{ 429146515Sru float_stack->title_used = 1; 430146515Sru} 431