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