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