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