ssconvert: enable --export-file-per-sheet for html and latex.
[gnumeric.git] / plugins / html / latex.c
blob722b33109946654d933cb6ffb3db8f3f9bc3b5d9
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * latex.c
5 * Copyright (C) 1999, 2000 Rasca, Berlin
6 * EMail: thron@gmx.de
8 * Copyright (C) 2001 Adrian Custer, Berkeley
9 * email: acuster@nature.berkeley.edu
11 * Copyright (C) 2001-2014 Andreas J. Guelzow, Edmonton
12 * email: aguelzow@pyrshep.ca
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <https://www.gnu.org/licenses/>.
30 * This file contains the LaTeX2e plugin functions.
33 * The LaTeX2e functions are named:
34 * latex_file_save()
35 * latex_table_visible_file_save()
36 * latex_table_file_save
41 #include <gnumeric-config.h>
42 #include <gnumeric.h>
43 #include <gnumeric-conf.h>
44 #include "latex.h"
45 #include <goffice/goffice.h>
46 #include <workbook-view.h>
47 #include <workbook.h>
48 #include <sheet.h>
49 #include <sheet-merge.h>
50 #include <style.h>
51 #include <style-color.h>
52 #include <font.h>
53 #include <cell.h>
54 #include <gnm-format.h>
55 #include <style-border.h>
56 #include <sheet-style.h>
57 #include <parse-util.h>
58 #include <rendered-value.h>
59 #include <cellspan.h>
60 #include <print-info.h>
62 #include <locale.h>
63 #include <gsf/gsf-output.h>
64 #include <string.h>
66 #define SHEET_SELECTION_KEY "sheet-selection"
68 typedef enum {
69 LATEX_NO_BORDER = 0,
70 LATEX_SINGLE_BORDER = 1,
71 LATEX_DOUBLE_BORDER = 2,
72 LATEX_MAX_BORDER
73 } latex_border_t;
75 typedef struct {
76 latex_border_t latex;
77 char const *vertical;
78 char const *horizontal;
79 } latex_border_translator_t;
81 /* the index into the following array is GnmStyleBorderType */
82 static latex_border_translator_t const border_styles[] = {
83 {LATEX_NO_BORDER, "", "~"},
84 {LATEX_SINGLE_BORDER, "|", "-"},
85 {LATEX_SINGLE_BORDER, "|", "-"},
86 {LATEX_SINGLE_BORDER, "|", "-"},
87 {LATEX_SINGLE_BORDER, "|", "-"},
88 {LATEX_DOUBLE_BORDER, "||","="},
89 {LATEX_DOUBLE_BORDER, "||","="},
90 {LATEX_SINGLE_BORDER, "|", "-"},
91 {LATEX_SINGLE_BORDER, "|", "-"},
92 {LATEX_SINGLE_BORDER, "|", "-"},
93 {LATEX_SINGLE_BORDER, "|", "-"},
94 {LATEX_SINGLE_BORDER, "|", "-"},
95 {LATEX_SINGLE_BORDER, "|", "-"},
96 {LATEX_NO_BORDER, "", ""}
99 typedef struct {
100 char const *p_1;
101 char const *p_2;
102 } latex_border_connectors_t;
105 static latex_border_connectors_t const conn_styles[LATEX_MAX_BORDER]
106 [LATEX_MAX_BORDER][LATEX_MAX_BORDER][LATEX_MAX_BORDER] = {
107 /* FIXME: once we are sure that none of the numbered */
108 /*entries are in fact needed we should removed the digits */
109 {{{{"",""}, { "",""}, { "",""}},
110 {{"",""}, { "|",""}, { "32",""}},
111 {{"",""}, { "11",""}, { "","|t:"}}},
112 {{{"",""}, { "",""}, { "",""}},
113 {{"","|"}, { "|",""}, { "33",""}},
114 {{"1",""}, { "13",""}, { "34",""}}},
115 {{{"",""}, { "",""}, { "|","|"}},
116 {{"","|b|"}, { "14",""}, { "|","|"}},
117 {{"","|b:"}, { "|b:",""}, { "|",":"}}}},
118 {{{{"",""}, { "",""}, { "",""}},
119 {{"",""}, { "|",""}, { "35",""}},
120 {{"","|"}, { "17",""}, { "36",""}}},
121 {{{"","|"}, { "|",""}, { "37",""}},
122 {{"|",""}, { "",""}, { "38",""}},
123 {{"4",""}, { "19",""}, { "39",""}}},
124 {{{"","|b|"}, { "20",""}, { "|","|"}},
125 {{"5",""}, { "21",""}, { "|","|"}},
126 {{"|b:",""}, { "22",""}, { "40",""}}}},
127 {{{{"",""}, { "23",""}, { ":t|",""}},
128 {{"|",""}, { "24",""}, { ":t|",""}},
129 {{"",""}, { "",""}, { ":t:",""}}},
130 {{{"7",""}, { "26",""}, { ":t|",""}},
131 {{"8",""}, { "27",""}, { "43",""}},
132 {{"",""}, { "",""}, { ":t:",""}}},
133 {{{":b|",""}, { "29",""}, { ":","|"}},
134 {{":b|",""}, { "30",""}, { ":|",""}},
135 {{":b:",""}, { ":b:",""}, { ":",":"}}}}
139 * latex_raw_str :
140 * @p: a pointer to a char, start of the string to be processed
141 * @output: output stream where the processed characters are written.
142 * @utf8: is this a utf8 string?
144 * @return:
145 * If @p is in form of \L{foo}, return the char pointer pointing to '}' of \L{foo}
146 * else return @p untouched;
148 * Check if @p is in form of \L{foo}.
149 * If it is, the exact "foo" will be put into @output, without any esacaping.
152 static char const *
153 latex_raw_str(char const *p, GsfOutput *output, gboolean utf8)
155 char const *p_begin, *p_orig = p;
156 int depth = 1;
157 if(strncasecmp(p, "\\L{", 3) == 0){
158 p += 3;
159 p_begin = p;
160 /* find the matching close bracket */
161 for(; *p; p = utf8 ? g_utf8_next_char(p) : p + 1){
162 switch(*p){ /* FIXME: how to put in unmatched brackets? */
163 case '{':
164 depth ++;
165 break;
166 case '}':
167 depth--;
168 if(depth == 0){
169 /* put the string beginning from p_begin to p to output */
170 gsf_output_write(output, p - p_begin, p_begin);
171 return p;
176 return p_orig;
181 * latex_fputs_utf :
183 * @p: a pointer to a char, start of the string to be processed.
184 * @output: output stream where the processed characters are written.
186 * This escapes any special LaTeX characters from the LaTeX engine,
187 * except the ones enclosed in "\L{" and "}".
188 * Re-ordered from Rasca's code to have most common first.
190 static void
191 latex_fputs_utf (char const *p, GsfOutput *output)
193 char const *rlt;
194 for (; *p; p = g_utf8_next_char (p)) {
195 switch (g_utf8_get_char (p)) {
197 /* These are the classic TeX symbols $ & % # _ { } (see Lamport, p.15) */
198 case '$': case '&': case '%': case '#':
199 case '_': case '{': case '}':
200 gsf_output_printf (output, "\\%c", *p);
201 break;
202 /* These are the other special characters ~ ^ \ (see Lamport, p.15) */
203 case '^': case '~':
204 gsf_output_printf (output, "\\%c{ }", *p);
205 break;
206 case '\\':
207 rlt = latex_raw_str(p, output, TRUE);
208 if(rlt == p)
209 gsf_output_puts (output, "$\\backslash$");
210 else
211 p = rlt;
212 break;
213 /* Are these available only in LaTeX through mathmode? */
214 case '>': case '<':
215 gsf_output_printf (output, "$%c$", *p);
216 break;
218 default:
219 gsf_output_write (output,
220 (g_utf8_next_char (p)) - p, p);
221 break;
227 * latex_math_fputs_utf :
229 * @p: a pointer to a char, start of the string to be processed.
230 * @output: output stream where the processed characters are written.
232 * This escapes any special LaTeX characters from the LaTeX engine,
233 * except the ones enclosed in "\L{" and "}".
235 * We assume that htis will be set in Mathematics mode.
237 static void
238 latex_math_fputs_utf (char const *p, GsfOutput *output)
240 char const *rlt;
241 for (; *p; p = g_utf8_next_char (p)) {
242 switch (g_utf8_get_char (p)) {
244 /* These are the classic TeX symbols $ & % # (see Lamport, p.15) */
245 case '$': case '&': case '%': case '#':
246 gsf_output_printf (output, "\\%c", *p);
247 break;
248 /* These are the other special characters ~ (see Lamport, p.15) */
249 case '~':
250 gsf_output_printf (output, "\\%c{ }", *p);
251 break;
252 case '\\':
253 rlt = latex_raw_str(p, output, TRUE);
254 if(rlt == p)
255 gsf_output_puts (output, "$\\backslash$");
256 else
257 p = rlt;
258 break;
259 default:
260 gsf_output_write (output,
261 (g_utf8_next_char (p)) - p, p);
262 break;
268 * latex_convert_latin_to_utf
270 * @text: string to convert
272 * return value needs to be freed with g_free
274 * call g_convert_with_fallback and also handle utf minus.
277 static char *
278 latex_convert_latin_to_utf (char const *text)
280 char * encoded_text = NULL;
282 gsize bytes_read;
283 gsize bytes_written;
285 if (g_utf8_strchr (text,-1, 0x2212) == NULL) {
286 encoded_text = g_convert_with_fallback
287 (text, strlen (text),
288 "ISO-8859-1", "UTF-8", (gchar *)"?",
289 &bytes_read, &bytes_written, NULL);
290 } else {
291 gunichar* ucs_string = NULL;
292 gunichar* this_unichar;
293 char *new_text;
294 glong items_read;
295 glong items_written;
297 ucs_string = g_utf8_to_ucs4_fast (text, -1, &items_written);
298 for (this_unichar = ucs_string; *this_unichar != '\0'; this_unichar++) {
299 if (*this_unichar == 0x2212)
300 *this_unichar = 0x002d;
302 new_text = g_ucs4_to_utf8 (ucs_string, -1, &items_read, &items_written, NULL);
303 g_free (ucs_string);
304 encoded_text = g_convert_with_fallback
305 (new_text, strlen (new_text),
306 "ISO-8859-1", "UTF-8", (gchar *)"?",
307 &bytes_read, &bytes_written, NULL);
308 g_free (new_text);
311 return encoded_text;
315 * latex_fputs_latin :
317 * @p: a pointer to a char, start of the string to be processed.
318 * @output: output stream where the processed characters are written.
320 * This escapes any special LaTeX characters from the LaTeX engine,
321 * except the ones enclosed in "\L{" and "}".
322 * Re-ordered from Rasca's code to have most common first.
324 static void
325 latex_fputs_latin (char const *text, GsfOutput *output)
327 char * encoded_text = NULL;
328 char const *p;
329 char const *rlt;
331 encoded_text = latex_convert_latin_to_utf (text);
333 for (p = encoded_text; *p; p++) {
334 switch (*p) {
336 /* These are the classic TeX symbols $ & % # _ { } (see Lamport, p.15) */
337 case '$': case '&': case '%': case '#':
338 case '_': case '{': case '}':
339 gsf_output_printf (output, "\\%c", *p);
340 break;
341 /* These are the other special characters ~ ^ \ (see Lamport, p.15) */
342 case '^': case '~':
343 gsf_output_printf (output, "\\%c{ }", *p);
344 break;
345 case '\\':
346 rlt = latex_raw_str(p, output, FALSE);
347 if(rlt == p)
348 gsf_output_puts (output, "$\\backslash$");
349 else
350 p = rlt;
351 break;
352 /* Are these available only in LaTeX through mathmode? */
353 case '>': case '<': case 'µ':
354 gsf_output_printf (output, "$%c$", *p);
355 break;
357 default:
358 gsf_output_write (output, 1, p);
359 break;
362 g_free (encoded_text);
366 * latex_math_fputs_latin :
368 * @p: a pointer to a char, start of the string to be processed.
369 * @output: output stream where the processed characters are written.
371 * This escapes any special LaTeX characters from the LaTeX engine,
372 * except the ones enclosed in "\L{" and "}".
374 * We assume that htis will be set in Mathematics mode.
376 static void
377 latex_math_fputs_latin (char const *text, GsfOutput *output)
379 char * encoded_text = NULL;
380 char const *p;
381 char const *rlt;
383 encoded_text = latex_convert_latin_to_utf (text);
385 for (p = encoded_text; *p; p++) {
386 switch (*p) {
388 /* These are the classic TeX symbols $ & % # (see Lamport, p.15) */
389 case '$': case '&': case '%': case '#':
390 gsf_output_printf (output, "\\%c", *p);
391 break;
392 /* These are the other special characters ~ (see Lamport, p.15) */
393 case '~':
394 gsf_output_printf (output, "\\%c{ }", *p);
395 break;
396 case '\\':
397 rlt = latex_raw_str(p, output, FALSE);
398 if(rlt == p)
399 gsf_output_puts (output, "$\\backslash$");
400 else
401 p = rlt;
402 break;
404 default:
405 gsf_output_write (output, 1, p);
406 break;
409 g_free (encoded_text);
412 static void
413 latex_fputs (char const *text, GsfOutput *output)
415 if (gnm_conf_get_plugin_latex_use_utf8 ())
416 latex_fputs_utf (text, output);
417 else
418 latex_fputs_latin (text, output);
421 static void
422 latex_math_fputs (char const *text, GsfOutput *output)
424 if (gnm_conf_get_plugin_latex_use_utf8 ())
425 latex_math_fputs_utf (text, output);
426 else
427 latex_math_fputs_latin (text, output);
430 static GnmValue *
431 cb_find_font_encodings (GnmCellIter const *iter, gboolean *fonts)
433 GnmCell *cell = iter->cell;
434 if (cell) {
435 char const *rs =
436 gnm_rendered_value_get_text
437 (gnm_cell_fetch_rendered_value (cell, TRUE));
438 while (*rs) {
439 gunichar ch = g_utf8_get_char (rs);
440 GUnicodeScript script = g_unichar_get_script (ch);
441 if (script > 0 && script <= G_UNICODE_SCRIPT_MANDAIC)
442 fonts [script] = 1;
443 rs = g_utf8_next_char (rs);
446 return NULL;
450 * latex2e_write_font_encodings writes
451 * \usepackage[T2A]{fontenc}
452 * in the presence of cyrillic text
455 static void
456 latex2e_write_font_encodings (GsfOutput *output, Sheet *sheet, GnmRange const *range)
458 gboolean *fonts = g_new0 (gboolean, G_UNICODE_SCRIPT_MANDAIC + 1);
460 sheet_foreach_cell_in_range
461 (sheet, CELL_ITER_IGNORE_BLANK | CELL_ITER_IGNORE_HIDDEN, range,
462 (CellIterFunc)&cb_find_font_encodings, fonts);
464 if (fonts[G_UNICODE_SCRIPT_CYRILLIC])
465 gsf_output_puts (output,
466 " \\usepackage[T2A]{fontenc}\n"
471 * latex2e_write_file_header:
473 * @output: Output stream where the cell contents will be written.
475 * This ouputs the LaTeX header. Kept separate for esthetics.
478 static void
479 latex2e_write_file_header(GsfOutput *output, Sheet *sheet, GnmRange const *range)
481 gboolean is_landscape = FALSE, use_utf8;
482 GtkPageOrientation orient = print_info_get_paper_orientation (sheet->print_info);
484 is_landscape = (orient == GTK_PAGE_ORIENTATION_LANDSCAPE ||
485 orient == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE);
486 use_utf8 = gnm_conf_get_plugin_latex_use_utf8 ();
488 gsf_output_puts (output,
489 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
490 "%% %%\n"
491 "%% This is the header of a LaTeX2e file exported from Gnumeric. %%\n"
492 "%% %%\n"
493 "%% This file can be compiled as it stands or included in another %%\n"
494 "%% LaTeX document. The table is based on the longtable package so %%\n"
495 "%% the longtable options (headers, footers...) can be set in the %%\n"
496 "%% preamble section below (see PRAMBLE). %%\n"
497 "%% %%\n"
498 "%% To include the file in another, the following two lines must be %%\n"
499 "%% in the including file: %%\n"
500 "%% \\def\\inputGnumericTable{} %%\n"
501 "%% at the beginning of the file and: %%\n"
502 "%% \\input{name-of-this-file.tex} %%\n"
503 "%% where the table is to be placed. Note also that the including %%\n"
504 "%% file must use the following packages for the table to be %%\n"
505 "%% rendered correctly: %%\n"
508 if (use_utf8)
509 gsf_output_puts (output,
510 "%% \\usepackage{ucs} %%\n"
511 "%% \\usepackage[utf8x]{inputenc} %%\n"
512 "%% \\usepackage[T2A]{fontenc} % if cyrillic is used %%\n"
514 else
515 gsf_output_puts (output,
516 "%% \\usepackage[latin1]{inputenc} %%\n"
519 gsf_output_puts (output,
520 "%% \\usepackage{color} %%\n"
521 "%% \\usepackage{array} %%\n"
522 "%% \\usepackage{longtable} %%\n"
523 "%% \\usepackage{calc} %%\n"
524 "%% \\usepackage{multirow} %%\n"
525 "%% \\usepackage{hhline} %%\n"
526 "%% \\usepackage{ifthen} %%\n"
527 "%% optionally (for landscape tables embedded in another document): %%\n"
528 "%% \\usepackage{lscape} %%\n"
529 "%% %%\n"
530 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
531 "\n"
532 "\n"
533 "\n"
534 "%% This section checks if we are begin input into another file or %%\n"
535 "%% the file will be compiled alone. First use a macro taken from %%\n"
536 "%% the TeXbook ex 7.7 (suggestion of Han-Wen Nienhuys). %%\n"
537 "\\def\\ifundefined#1{\\expandafter\\ifx\\csname#1\\endcsname\\relax}\n"
538 "\n"
539 "\n"
540 "%% Check for the \\def token for inputed files. If it is not %%\n"
541 "%% defined, the file will be processed as a standalone and the %%\n"
542 "%% preamble will be used. %%\n"
543 "\\ifundefined{inputGnumericTable}\n"
544 "\n"
545 "%% We must be able to close or not the document at the end. %%\n"
546 " \\def\\gnumericTableEnd{\\end{document}}\n"
547 "\n"
548 "\n"
549 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
550 "%% %%\n"
551 "%% This is the PREAMBLE. Change these values to get the right %%\n"
552 "%% paper size and other niceties. %%\n"
553 "%% %%\n"
554 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
555 "\n"
557 if (is_landscape)
558 gsf_output_puts (output,
559 " \\documentclass[12pt%\n"
560 " ,landscape%\n"
561 " ]{report}\n"
563 else
564 gsf_output_puts (output,
565 " \\documentclass[12pt%\n"
566 " %,landscape%\n"
567 " ]{report}\n"
572 if (gnm_conf_get_plugin_latex_use_utf8 ()) {
573 gsf_output_puts (output,
574 " \\usepackage{ucs}\n"
575 " \\usepackage[utf8x]{inputenc}\n"
577 latex2e_write_font_encodings (output, sheet, range);
578 } else
579 gsf_output_puts (output,
580 " \\usepackage[latin1]{inputenc}\n"
583 gsf_output_puts (output,
584 " \\usepackage{fullpage}\n"
585 " \\usepackage{color}\n"
586 " \\usepackage{array}\n"
587 " \\usepackage{longtable}\n"
588 " \\usepackage{calc}\n"
589 " \\usepackage{multirow}\n"
590 " \\usepackage{hhline}\n"
591 " \\usepackage{ifthen}\n"
592 "\n"
593 " \\begin{document}\n"
594 "\n"
595 "\n"
596 "%% End of the preamble for the standalone. The next section is for %%\n"
597 "%% documents which are included into other LaTeX2e files. %%\n"
598 "\\else\n"
599 "\n"
600 "%% We are not a stand alone document. For a regular table, we will %%\n"
601 "%% have no preamble and only define the closing to mean nothing. %%\n"
602 " \\def\\gnumericTableEnd{}\n"
603 "\n"
604 "%% If we want landscape mode in an embedded document, comment out %%\n"
605 "%% the line above and uncomment the two below. The table will %%\n"
606 "%% begin on a new page and run in landscape mode. %%\n"
607 "% \\def\\gnumericTableEnd{\\end{landscape}}\n"
608 "% \\begin{landscape}\n"
609 "\n"
610 "\n"
611 "%% End of the else clause for this file being \\input. %%\n"
612 "\\fi\n"
613 "\n"
614 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
615 "%% %%\n"
616 "%% The rest is the gnumeric table, except for the closing %%\n"
617 "%% statement. Changes below will alter the table\'s appearance. %%\n"
618 "%% %%\n"
619 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
620 "\n"
621 "\\providecommand{\\gnumericmathit}[1]{#1} \n"
622 "%% Uncomment the next line if you would like your numbers to be in %%\n"
623 "%% italics if they are italizised in the gnumeric table. %%\n"
624 "%\\renewcommand{\\gnumericmathit}[1]{\\mathit{#1}}\n"
625 "\\providecommand{\\gnumericPB}[1]%\n"
626 "{\\let\\gnumericTemp=\\\\#1\\let\\\\=\\gnumericTemp\\hspace{0pt}}\n"
627 " \\ifundefined{gnumericTableWidthDefined}\n"
628 " \\newlength{\\gnumericTableWidth}\n"
629 " \\newlength{\\gnumericTableWidthComplete}\n"
630 " \\newlength{\\gnumericMultiRowLength}\n"
631 " \\global\\def\\gnumericTableWidthDefined{}\n"
632 " \\fi\n"
633 "%% The following setting protects this code from babel shorthands. %%\n"
634 " \\ifthenelse{\\isundefined{\\languageshorthands}}{}{\\languageshorthands{english}}"
635 "\n"
636 "%% The default table format retains the relative column widths of %%\n"
637 "%% gnumeric. They can easily be changed to c, r or l. In that case %%\n"
638 "%% you may want to comment out the next line and uncomment the one %%\n"
639 "%% thereafter %%\n"
640 "\\providecommand\\gnumbox{\\makebox[0pt]}\n"
641 "%%\\providecommand\\gnumbox[1][]{\\makebox}\n"
642 "\n"
643 "%% to adjust positions in multirow situations %%\n"
644 "\\setlength{\\bigstrutjot}{\\jot}\n"
645 "\\setlength{\\extrarowheight}{\\doublerulesep}\n"
646 "\n"
647 "%% The \\setlongtables command keeps column widths the same across %%\n"
648 "%% pages. Simply comment out next line for varying column widths. %%\n"
649 "\\setlongtables\n"
650 "\n"
656 * latex2e_write_table_header:
658 * @output: Output stream where the cell contents will be written.
659 * @num_cols: The number of columns in the table
661 * A convenience function that also helps make nicer code.
663 static void
664 latex2e_write_table_header(GsfOutput *output, int num_cols)
666 int col;
669 gsf_output_puts (output,
670 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
671 "%% The longtable options. (Caption, headers... see Goosens, p.124) %%\n"
672 "%\t\\caption{The Table Caption.} \\\\ %\n"
673 "% \\hline % Across the top of the table.\n"
674 "%% The rest of these options are table rows which are placed on %%\n"
675 "%% the first, last or every page. Use \\multicolumn if you want. %%\n"
676 "\n"
677 "%% Header for the first page. %%\n"
680 gsf_output_printf (output, "%%\t\\multicolumn{%d}{c}{The First Header} \\\\ \\hline \n", num_cols);
681 gsf_output_printf (output, "%%\t\\multicolumn{1}{c}{colTag}\t%%Column 1\n");
682 for (col = 2 ; col < num_cols; col++)
683 gsf_output_printf (output, "%%\t&\\multicolumn{1}{c}{colTag}\t%%Column %d\n",col);
684 gsf_output_printf (output, "%%\t&\\multicolumn{1}{c}{colTag}\t\\\\ \\hline %%Last column\n");
685 gsf_output_printf (output, "%%\t\\endfirsthead\n\n");
687 gsf_output_printf (output, "%%%% The running header definition. %%%%\n");
688 gsf_output_printf (output, "%%\t\\hline\n");
689 gsf_output_printf (output, "%%\t\\multicolumn{%d}{l}{\\ldots\\small\\slshape continued} \\\\ \\hline\n", num_cols);
690 gsf_output_printf (output, "%%\t\\multicolumn{1}{c}{colTag}\t%%Column 1\n");
691 for (col = 2 ; col < num_cols; col++)
692 gsf_output_printf (output, "%%\t&\\multicolumn{1}{c}{colTag}\t%%Column %d\n",col);
693 gsf_output_printf (output, "%%\t&\\multicolumn{1}{c}{colTag}\t\\\\ \\hline %%Last column\n");
694 gsf_output_printf (output, "%%\t\\endhead\n\n");
696 gsf_output_printf (output, "%%%% The running footer definition. %%%%\n");
697 gsf_output_printf (output, "%%\t\\hline\n");
698 gsf_output_printf (output, "%%\t\\multicolumn{%d}{r}{\\small\\slshape continued\\ldots}", num_cols);
699 gsf_output_printf (output, " \\\\\n");
700 gsf_output_printf (output, "%%\t\\endfoot\n\n");
702 gsf_output_printf (output, "%%%% The ending footer definition. %%%%\n");
703 gsf_output_printf (output, "%%\t\\multicolumn{%d}{c}{That's all folks} \\\\ \\hline \n", num_cols);
704 gsf_output_printf (output, "%%\t\\endlastfoot\n");
705 gsf_output_puts (output, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n");
710 * latex2e_find_vline:
712 * @col:
713 * @row:
714 * @sheet:
715 * @which_border: GnmStyleElement (MSTYLE_BORDER_LEFT or MSTYLE_BORDER_RIGHT)
717 * Determine the border style
720 static GnmStyleBorderType
721 latex2e_find_this_vline (int col, int row, Sheet *sheet, GnmStyleElement which_border)
723 GnmBorder const *border;
724 GnmStyle const *style;
726 if (col < 0 || row < 0)
727 return GNM_STYLE_BORDER_NONE;
729 style = sheet_style_get (sheet, col, row);
730 border = gnm_style_get_border (style, which_border);
732 if (!gnm_style_border_is_blank (border))
733 return border->line_type;
735 if (which_border == MSTYLE_BORDER_LEFT) {
736 if (col <= 0)
737 return GNM_STYLE_BORDER_NONE;
738 style = sheet_style_get (sheet, col - 1, row);
739 border = gnm_style_get_border (style, MSTYLE_BORDER_RIGHT);
740 return ((border == NULL) ? GNM_STYLE_BORDER_NONE : border->line_type);
741 } else {
742 if ((col+1) >= colrow_max (TRUE, sheet))
743 return GNM_STYLE_BORDER_NONE;
744 style = sheet_style_get (sheet, col + 1, row);
745 border = gnm_style_get_border (style, MSTYLE_BORDER_LEFT);
746 return ((border == NULL) ? GNM_STYLE_BORDER_NONE : border->line_type);
749 return GNM_STYLE_BORDER_NONE;
752 static GnmStyleBorderType
753 latex2e_find_vline (int col, int row, Sheet *sheet, GnmStyleElement which_border)
755 /* We are checking for NONE boreders first since there should only be a few merged ranges */
756 GnmStyleBorderType result = latex2e_find_this_vline (col, row, sheet, which_border);
757 GnmCellPos pos;
758 GnmRange const * range;
760 if (result == GNM_STYLE_BORDER_NONE)
761 return GNM_STYLE_BORDER_NONE;
763 pos.col = col;
764 pos.row = row;
765 range = gnm_sheet_merge_contains_pos (sheet, &pos);
767 if (range) {
768 if ((which_border == MSTYLE_BORDER_LEFT && col == range->start.col)
769 || (which_border == MSTYLE_BORDER_RIGHT&& col == range->end.col))
770 return result;
771 else
772 return GNM_STYLE_BORDER_NONE;
774 return result;
778 * latex2e_print_vert_border:
780 * @output: Output stream where the cell contents will be written.
781 * @clines: GnmStyleBorderType indicating the type of border
784 static void
785 latex2e_print_vert_border (GsfOutput *output, GnmStyleBorderType style)
787 g_return_if_fail (/* style >= 0 && */ style < G_N_ELEMENTS (border_styles));
789 gsf_output_printf (output, "%s", border_styles[style].vertical);
793 * latex2e_write_blank_multicolumn_cell:
795 * @output: output stream where the cell contents will be written.
796 * @star_col:
797 * @start_row:
798 * @num_merged_cols: an integer value of the number of columns to merge.
799 * @num_merged_rows: an integer value of the number of rows to merge.
800 * @sheet: the current sheet.
802 * This function creates all the LaTeX code for the cell of a table (i.e. all
803 * the code that might fall between two ampersands (&)), assuming that
804 * the cell is in fact NULL. We therefore have only to worry about a few
805 * formatting issues.
808 static void
809 latex2e_write_blank_multicolumn_cell (GsfOutput *output, int start_col,
810 G_GNUC_UNUSED int start_row,
811 int num_merged_cols, int num_merged_rows,
812 gint index,
813 GnmStyleBorderType *borders, Sheet *sheet)
815 int merge_width = 0;
816 GnmStyleBorderType left_border = GNM_STYLE_BORDER_NONE;
817 GnmStyleBorderType right_border = GNM_STYLE_BORDER_NONE;
819 if (num_merged_cols > 1 || num_merged_rows > 1) {
820 ColRowInfo const * ci;
821 int i;
823 for (i = 0; i < num_merged_cols; i++) {
824 ci = sheet_col_get_info (sheet, start_col + i);
825 merge_width += ci->size_pixels;
829 if (index == 0) {
830 left_border = *borders;
832 right_border = borders[index + num_merged_cols];
834 /* We only set up a multicolumn command if necessary */
835 if (num_merged_cols > 1) {
836 int i;
838 /* Open the multicolumn statement. */
839 gsf_output_printf (output, "\\multicolumn{%d}{", num_merged_cols);
841 if (left_border != GNM_STYLE_BORDER_NONE)
842 latex2e_print_vert_border (output, left_border);
844 if (num_merged_rows > 1) {
845 gsf_output_printf (output, "c");
846 } else {
847 gsf_output_printf (output, "p{");
848 for (i = 0; i < num_merged_cols; i++) {
849 gsf_output_printf (output, "\t\\gnumericCol%s+%%\n",
850 col_name (start_col + i));
852 gsf_output_printf (output, "\t\\tabcolsep*2*%i}", num_merged_cols - 1);
855 if (right_border != GNM_STYLE_BORDER_NONE)
856 latex2e_print_vert_border (output, right_border);
858 /*Close the right delimiter, as above. Also open the text delimiter.*/
859 gsf_output_printf (output,"}%%\n\t{");
860 } else if (left_border != GNM_STYLE_BORDER_NONE || right_border != GNM_STYLE_BORDER_NONE) {
862 /* Open the multicolumn statement. */
863 gsf_output_printf (output, "\\multicolumn{1}{");
865 if (left_border != GNM_STYLE_BORDER_NONE)
866 latex2e_print_vert_border (output, left_border);
868 /* Drop in the left hand format delimiter. */
869 gsf_output_printf (output, "p{\\gnumericCol%s}", col_name(start_col));
871 if (right_border != GNM_STYLE_BORDER_NONE)
872 latex2e_print_vert_border (output, right_border);
874 /*Close the right delimiter, as above. Also open the text delimiter.*/
875 gsf_output_printf (output,"}%%\n\t{");
879 if (num_merged_rows > 1) {
880 int i;
881 /* Open the multirow statement. */
882 gsf_output_printf (output, "\\setlength{\\gnumericMultiRowLength}{0pt}%%\n");
883 for (i = 0; i < num_merged_cols; i++) {
884 gsf_output_printf (output, "\t \\addtolength{\\gnumericMultiRowLength}{\\gnumericCol%s}%%\n", col_name (start_col + i));
885 if (i>0)
886 gsf_output_printf (output, "\t \\addtolength{\\gnumericMultiRowLength}{\\tabcolsep}%%\n");
888 gsf_output_printf (output, "\t \\multirow{%i}[%i]{\\gnumericMultiRowLength}{%%\n\t ", num_merged_rows, num_merged_rows/2);
890 /* Close the multirowtext. */
891 gsf_output_printf (output, "}");
894 /* Close the multicolumn text bracket. */
895 if (num_merged_cols > 1 || left_border != GNM_STYLE_BORDER_NONE
896 || right_border != GNM_STYLE_BORDER_NONE)
897 gsf_output_printf (output, "}");
899 /* And we are done. */
900 gsf_output_printf (output, "\n");
906 * latex2e_write_multicolumn_cell:
908 * @output: output stream where the cell contents will be written.
909 * @cell: the cell whose contents are to be written.
910 * @star_col:
911 * @num_merged_cols: an integer value of the number of columns to merge.
912 * @num_merged_rows: an integer value of the number of rows to merge.
913 * @sheet: the current sheet.
915 * This function creates all the LaTeX code for the cell of a table (i.e. all
916 * the code that might fall between two ampersands (&)).
918 * Note: we are _not_ putting single cell into \multicolumns since this
919 * makes it much more difficult to change column widths later on.
921 static void
922 latex2e_write_multicolumn_cell (GsfOutput *output, GnmCell *cell, int start_col,
923 int num_merged_cols, int num_merged_rows,
924 gint index,
925 GnmStyleBorderType *borders, Sheet *sheet)
927 char * rendered_string;
928 gushort r,g,b;
929 gboolean wrap = FALSE;
930 GOFormatFamily cell_format_family;
931 int merge_width = 0;
932 GnmStyleBorderType left_border = GNM_STYLE_BORDER_NONE;
933 GnmStyleBorderType right_border = GNM_STYLE_BORDER_NONE;
935 /* Print the cell according to its style. */
936 GnmStyle const *style = gnm_cell_get_style (cell);
937 gboolean hidden = gnm_style_get_contents_hidden (style);
939 g_return_if_fail (style != NULL);
941 if (num_merged_cols > 1 || num_merged_rows > 1) {
942 ColRowInfo const * ci;
943 int i;
945 for (i = 0; i < num_merged_cols; i++) {
946 ci = sheet_col_get_info (sheet, start_col + i);
947 merge_width += ci->size_pixels;
951 if (index == 0) {
952 left_border = *borders;
954 right_border = borders[index + num_merged_cols];
956 /* We only set up a multicolumn command if necessary */
957 if (num_merged_cols > 1) {
958 int i;
960 /* Open the multicolumn statement. */
961 gsf_output_printf (output, "\\multicolumn{%d}{", num_merged_cols);
963 if (left_border != GNM_STYLE_BORDER_NONE)
964 latex2e_print_vert_border (output, left_border);
966 if (num_merged_rows > 1) {
967 gsf_output_printf (output, "c");
968 } else {
969 gsf_output_printf (output, "p{");
970 for (i = 0; i < num_merged_cols; i++) {
971 gsf_output_printf (output, "\t\\gnumericCol%s+%%\n",
972 col_name (start_col + i));
974 gsf_output_printf (output, "\t\\tabcolsep*2*%i}", num_merged_cols - 1);
977 if (right_border != GNM_STYLE_BORDER_NONE)
978 latex2e_print_vert_border (output, right_border);
980 /*Close the right delimiter, as above. Also open the text delimiter.*/
981 gsf_output_printf (output,"}%%\n\t{");
982 } else if (left_border != GNM_STYLE_BORDER_NONE || right_border != GNM_STYLE_BORDER_NONE) {
984 /* Open the multicolumn statement. */
985 gsf_output_printf (output, "\\multicolumn{1}{");
987 if (left_border != GNM_STYLE_BORDER_NONE)
988 latex2e_print_vert_border (output, left_border);
990 /* Drop in the left hand format delimiter. */
991 gsf_output_printf (output, "p{\\gnumericCol%s}", col_name(start_col));
993 if (right_border != GNM_STYLE_BORDER_NONE)
994 latex2e_print_vert_border (output, right_border);
996 /*Close the right delimiter, as above. Also open the text delimiter.*/
997 gsf_output_printf (output,"}%%\n\t{");
1001 if (num_merged_rows > 1) {
1002 int i;
1003 /* Open the multirow statement. */
1004 gsf_output_printf (output, "\\setlength{\\gnumericMultiRowLength}{0pt}%%\n");
1005 for (i = 0; i < num_merged_cols; i++) {
1006 gsf_output_printf (output, "\t \\addtolength{\\gnumericMultiRowLength}{\\gnumericCol%s}%%\n", col_name (start_col + i));
1007 if (i>0)
1008 gsf_output_printf (output, "\t \\addtolength{\\gnumericMultiRowLength}{\\tabcolsep}%%\n");
1010 gsf_output_printf (output,
1011 "\t \\multirow{%i}[%i]{\\gnumericMultiRowLength}"
1012 "{\\parbox{\\gnumericMultiRowLength}{%%\n\t ",
1013 num_merged_rows, num_merged_rows/2);
1017 /* Send the alignment of the cell through a routine to deal with
1018 * GNM_HALIGN_GENERAL and then deal with the three cases. */
1019 switch (gnm_style_default_halign (style, cell)) {
1020 case GNM_HALIGN_RIGHT:
1021 gsf_output_printf (output, "\\gnumericPB{\\raggedleft}");
1022 break;
1023 case GNM_HALIGN_DISTRIBUTED:
1024 case GNM_HALIGN_CENTER:
1025 case GNM_HALIGN_CENTER_ACROSS_SELECTION:
1026 gsf_output_printf (output, "\\gnumericPB{\\centering}");
1027 break;
1028 case GNM_HALIGN_LEFT:
1029 gsf_output_printf (output, "\\gnumericPB{\\raggedright}");
1030 break;
1031 case GNM_HALIGN_JUSTIFY:
1032 break;
1033 default:
1034 break;
1037 /* Check whether we should do word wrapping */
1038 wrap = gnm_style_get_wrap_text (style);
1040 /* if we don't wrap put it into an mbox, adjusted to width 0 to avoid moving */
1041 /* it to the second line of the parbox */
1042 if (!wrap)
1043 switch (gnm_style_default_halign (style, cell)) {
1044 case GNM_HALIGN_RIGHT:
1045 gsf_output_printf (output, "\\gnumbox[r]{");
1046 break;
1047 case GNM_HALIGN_DISTRIBUTED:
1048 case GNM_HALIGN_CENTER:
1049 case GNM_HALIGN_CENTER_ACROSS_SELECTION:
1050 gsf_output_printf (output, "\\gnumbox{");
1051 break;
1052 case GNM_HALIGN_LEFT:
1053 gsf_output_printf (output, "\\gnumbox[l]{");
1054 break;
1055 case GNM_HALIGN_JUSTIFY:
1056 gsf_output_printf (output, "\\gnumbox[s]{");
1057 break;
1058 default:
1059 gsf_output_printf (output, "\\makebox{");
1060 break;
1063 if (!gnm_cell_is_empty (cell)) {
1064 /* Check the foreground (text) colour. */
1065 GOColor fore = gnm_cell_get_render_color (cell);
1066 if (fore == 0)
1067 r = g = b = 0;
1068 else {
1069 r = GO_COLOR_UINT_R (fore);
1070 g = GO_COLOR_UINT_G (fore);
1071 b = GO_COLOR_UINT_B (fore);
1073 if (r != 0 || g != 0 || b != 0) {
1074 gchar buffer[7] = {0};
1075 gsf_output_printf (output, "{\\color[rgb]{");
1076 g_ascii_formatd (buffer, 7, "%.2f",r/255.0);
1077 gsf_output_printf (output, "%s,", buffer);
1078 g_ascii_formatd (buffer, 7, "%.2f",g/255.0);
1079 gsf_output_printf (output, "%s,", buffer);
1080 g_ascii_formatd (buffer, 7, "%.2f",b/255.0);
1081 gsf_output_printf (output, "%s", buffer);
1082 gsf_output_printf (output, "} ");
1085 /* Establish the font's style for the styles that can be addressed by LaTeX.
1086 * More complicated efforts (like changing fonts) are left to the user.
1089 if (hidden)
1090 gsf_output_printf (output, "\\phantom{");
1092 if (font_is_monospaced (style))
1093 gsf_output_printf (output, "\\texttt{");
1094 else if (font_is_sansserif (style))
1095 gsf_output_printf (output, "\\textsf{");
1096 if (gnm_style_get_font_bold (style))
1097 gsf_output_printf (output, "\\textbf{");
1098 if (gnm_style_get_font_italic (style))
1099 gsf_output_printf (output, "\\textit{");
1102 cell_format_family = go_format_get_family (gnm_cell_get_format (cell));
1103 if (cell_format_family == GO_FORMAT_NUMBER ||
1104 cell_format_family == GO_FORMAT_CURRENCY ||
1105 cell_format_family == GO_FORMAT_PERCENTAGE ||
1106 cell_format_family == GO_FORMAT_FRACTION ||
1107 cell_format_family == GO_FORMAT_SCIENTIFIC){
1108 gsf_output_printf (output, "$");
1109 if (gnm_style_get_font_italic(style))
1110 gsf_output_printf (output, "\\gnumericmathit{");
1112 /* Print the cell contents. */
1113 rendered_string = gnm_cell_get_rendered_text (cell);
1114 latex_math_fputs (rendered_string, output);
1115 g_free (rendered_string);
1117 if (gnm_style_get_font_italic(style))
1118 gsf_output_printf (output, "}");
1119 gsf_output_printf (output, "$");
1120 } else {
1121 /* Print the cell contents. */
1122 rendered_string = gnm_cell_get_rendered_text (cell);
1123 latex_fputs (rendered_string, output);
1124 g_free (rendered_string);
1127 /* Close the styles for the cell. */
1128 if (gnm_style_get_font_italic (style))
1129 gsf_output_printf (output, "}");
1130 if (gnm_style_get_font_bold (style))
1131 gsf_output_printf (output, "}");
1132 if (font_is_monospaced (style))
1133 gsf_output_printf (output, "}");
1134 else if (font_is_sansserif (style))
1135 gsf_output_printf (output, "}");
1136 if (hidden)
1137 gsf_output_printf (output, "}");
1138 if (r != 0 || g != 0 || b != 0)
1139 gsf_output_printf (output, "}");
1142 /* if we don't wrap close the mbox */
1143 if (!wrap)
1144 gsf_output_printf (output, "}");
1146 /* Close the multirowtext. */
1147 if (num_merged_rows > 1)
1148 gsf_output_printf (output, "}}");
1150 /* Close the multicolumn text bracket. */
1151 if (num_merged_cols > 1 || left_border != GNM_STYLE_BORDER_NONE
1152 || right_border != GNM_STYLE_BORDER_NONE)
1153 gsf_output_printf (output, "}");
1155 /* And we are done. */
1156 gsf_output_printf (output, "\n");
1161 * latex2e_find_hhlines :
1163 * @clines: array of GnmStyleBorderType* indicating the type of border
1164 * @length: (remaining) positions in clines
1165 * @col:
1166 * @row:
1167 * @sheet:
1169 * Determine the border style
1173 static gboolean
1174 latex2e_find_hhlines (GnmStyleBorderType *clines, G_GNUC_UNUSED int length, int col, int row,
1175 Sheet *sheet, GnmStyleElement type)
1177 GnmStyle const *style;
1178 GnmBorder const *border;
1179 GnmRange const *range;
1180 GnmCellPos pos;
1182 style = sheet_style_get (sheet, col, row);
1183 border = gnm_style_get_border (style, type);
1184 if (gnm_style_border_is_blank (border))
1185 return FALSE;
1186 clines[0] = border->line_type;
1188 pos.col = col;
1189 pos.row = row;
1190 range = gnm_sheet_merge_contains_pos (sheet, &pos);
1191 if (range) {
1192 if ((type == MSTYLE_BORDER_TOP && row > range->start.row)
1193 || (type == MSTYLE_BORDER_BOTTOM&& row < range->end.row)) {
1194 clines[0] = GNM_STYLE_BORDER_NONE;
1195 return FALSE;
1199 return TRUE;
1204 * latex2e_print_hhline :
1206 * @output: output stream where the cell contents will be written.
1207 * @clines: an array of GnmStyleBorderType* indicating the type of border
1208 * @n: the number of elements in clines
1210 * This procedure prints an hhline command according to the content
1211 * of clines.
1214 static void
1215 latex2e_print_hhline (GsfOutput *output, GnmStyleBorderType *clines, int n, GnmStyleBorderType *prev_vert,
1216 GnmStyleBorderType *next_vert)
1218 int col;
1219 gsf_output_printf (output, "\\hhline{");
1220 gsf_output_printf (output, "%s", conn_styles[LATEX_NO_BORDER]
1221 [prev_vert ? border_styles[prev_vert[0]].latex : LATEX_NO_BORDER]
1222 [border_styles[clines[0]].latex]
1223 [next_vert ? border_styles[next_vert[0]].latex : LATEX_NO_BORDER].p_1);
1224 gsf_output_printf (output, "%s", conn_styles[LATEX_NO_BORDER]
1225 [prev_vert ? border_styles[prev_vert[0]].latex : LATEX_NO_BORDER]
1226 [border_styles[clines[0]].latex]
1227 [next_vert ? border_styles[next_vert[0]].latex : LATEX_NO_BORDER].p_2);
1228 for (col = 0; col < n - 1; col++) {
1229 gsf_output_printf (output, "%s", border_styles[clines[col]].horizontal);
1230 gsf_output_printf (output, "%s", conn_styles[border_styles[clines[col]].latex]
1231 [prev_vert ? border_styles[prev_vert[col + 1]].latex :
1232 LATEX_NO_BORDER]
1233 [border_styles[clines[col+1]].latex]
1234 [next_vert ? border_styles[next_vert[col + 1]].latex :
1235 LATEX_NO_BORDER].p_1);
1236 gsf_output_printf (output, "%s", conn_styles[border_styles[clines[col]].latex]
1237 [prev_vert ? border_styles[prev_vert[col + 1]].latex :
1238 LATEX_NO_BORDER]
1239 [border_styles[clines[col+1]].latex]
1240 [next_vert ? border_styles[next_vert[col + 1]].latex :
1241 LATEX_NO_BORDER].p_2);
1243 gsf_output_printf (output, "%s", border_styles[clines[n - 1]].horizontal);
1244 gsf_output_printf (output, "%s", conn_styles[border_styles[clines[n - 1]].latex]
1245 [prev_vert ? border_styles[prev_vert[n]].latex : LATEX_NO_BORDER]
1246 [LATEX_NO_BORDER]
1247 [next_vert ? border_styles[next_vert[n]].latex :
1248 LATEX_NO_BORDER].p_1);
1249 gsf_output_printf (output, "%s", conn_styles[border_styles[clines[n - 1]].latex]
1250 [prev_vert ? border_styles[prev_vert[n]].latex : LATEX_NO_BORDER]
1251 [LATEX_NO_BORDER]
1252 [next_vert ? border_styles[next_vert[n]].latex :
1253 LATEX_NO_BORDER].p_2);
1255 gsf_output_printf (output, "}\n");
1258 static GnmRange
1259 file_saver_sheet_get_extent (Sheet *sheet)
1261 GnmRangeRef *range
1262 = g_object_get_data (G_OBJECT (sheet->workbook),
1263 "ssconvert-range");
1264 if (range) {
1265 Sheet *start_sheet, *end_sheet;
1266 GnmEvalPos ep;
1267 GnmRange r;
1269 gnm_rangeref_normalize (range,
1270 eval_pos_init_sheet (&ep, sheet),
1271 &start_sheet, &end_sheet,
1272 &r);
1273 if (start_sheet == sheet)
1274 return r;
1276 return sheet_get_extent (sheet, TRUE, TRUE);
1280 * latex_file_save : The LaTeX2e exporter plugin function.
1282 * @FileSaver: New structure for file plugins. I don't understand.
1283 * @IOcontext: currently not used but reserved for the future.
1284 * @WorkbookView: this provides the way to access the sheet being exported.
1285 * @filename: where we'll write.
1287 * This writes the top sheet of a Gnumeric workbook to a LaTeX2e longtable. We
1288 * check for merges here, then call the function latex2e_write_multicolum_cell()
1289 * to render the format and contents of the cell.
1291 void
1292 latex_file_save (G_GNUC_UNUSED GOFileSaver const *fs, G_GNUC_UNUSED GOIOContext *io_context,
1293 WorkbookView const *wb_view, GsfOutput *output)
1295 Workbook *wb = wb_view_get_workbook (wb_view);
1296 GnmCell *cell;
1297 Sheet *current_sheet;
1298 GnmRange total_range;
1299 GnmRange const *merge_range;
1300 int row, col, num_cols, length;
1301 int num_merged_cols, num_merged_rows;
1302 GnmStyleBorderType *clines, *this_clines;
1303 GnmStyleBorderType *prev_vert = NULL, *next_vert = NULL, *this_vert;
1304 gboolean needs_hline;
1305 GPtrArray *sel;
1307 /* Get the sheet and its range from the plugin function argument. */
1308 sel = g_object_get_data (G_OBJECT (wb), SHEET_SELECTION_KEY);
1309 current_sheet = sel && sel->len
1310 ? g_ptr_array_index (sel, 0)
1311 : wb_view_cur_sheet(wb_view);
1312 total_range = file_saver_sheet_get_extent (current_sheet);
1314 /* This is the preamble of the LaTeX2e file. */
1315 latex2e_write_file_header(output, current_sheet, &total_range);
1317 num_cols = total_range.end.col - total_range.start.col + 1;
1319 gsf_output_printf (output, "\\setlength\\gnumericTableWidth{%%\n");
1320 for (col = total_range.start.col; col <= total_range.end.col; col++) {
1321 ColRowInfo const * ci;
1322 ci = sheet_col_get_info (current_sheet, col);
1323 gsf_output_printf (output, "\t%ipt+%%\n", ci->size_pixels * 10 / 12);
1325 gsf_output_printf (output, "0pt}\n\\def\\gumericNumCols{%i}\n", num_cols);
1327 gsf_output_puts (output, ""
1328 "\\setlength\\gnumericTableWidthComplete{\\gnumericTableWidth+%\n"
1329 " \\tabcolsep*\\gumericNumCols*2+\\arrayrulewidth*\\gumericNumCols}\n"
1330 "\\ifthenelse{\\lengthtest{\\gnumericTableWidthComplete > \\linewidth}}%\n"
1331 " {\\def\\gnumericScale{\\ratio{\\linewidth-%\n"
1332 " \\tabcolsep*\\gumericNumCols*2-%\n"
1333 " \\arrayrulewidth*\\gumericNumCols}%\n"
1334 "{\\gnumericTableWidth}}}%\n"
1335 "{\\def\\gnumericScale{1}}\n"
1336 "\n"
1337 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
1338 "%% %%\n"
1339 "%% The following are the widths of the various columns. We are %%\n"
1340 "%% defining them here because then they are easier to change. %%\n"
1341 "%% Depending on the cell formats we may use them more than once. %%\n"
1342 "%% %%\n"
1343 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
1344 "\n"
1347 for (col = total_range.start.col; col <= total_range.end.col; col++) {
1348 ColRowInfo const * ci;
1349 char const *colname = col_name (col);
1351 ci = sheet_col_get_info (current_sheet, col);
1352 gsf_output_printf (output, "\\ifthenelse{\\isundefined{\\gnumericCol%s}}"
1353 "{\\newlength{\\gnumericCol%s}}{}\\settowidth{\\gnumericCol%s}"
1354 "{\\begin{tabular}{@{}p{%ipt*\\gnumericScale}@{}}x\\end{tabular}}\n",
1355 colname, colname, colname, ci->size_pixels * 10 / 12);
1358 /* Start outputting the table. */
1359 gsf_output_printf (output, "\n\\begin{longtable}[c]{%%\n");
1360 for (col = total_range.start.col; col <= total_range.end.col; col++) {
1361 gsf_output_printf (output, "\tb{\\gnumericCol%s}%%\n", col_name (col));
1363 gsf_output_printf (output, "\t}\n\n");
1365 /* Output the table header. */
1366 latex2e_write_table_header (output, num_cols);
1369 /* Step through the sheet, writing cells as appropriate. */
1370 for (row = total_range.start.row; row <= total_range.end.row; row++) {
1371 ColRowInfo const * ri;
1372 ri = sheet_row_get_info (current_sheet, row);
1373 if (ri->needs_respan)
1374 row_calc_spans ((ColRowInfo *) ri, row, current_sheet);
1376 /* We need to check for horizontal borders at the top of this row */
1377 length = num_cols;
1378 clines = g_new0 (GnmStyleBorderType, length);
1379 needs_hline = FALSE;
1380 this_clines = clines;
1381 for (col = total_range.start.col; col <= total_range.end.col; col++) {
1382 needs_hline = latex2e_find_hhlines (this_clines, length, col, row,
1383 current_sheet, MSTYLE_BORDER_TOP)
1384 || needs_hline;
1385 this_clines ++;
1386 length--;
1388 /* or at the bottom of the previous */
1389 if (row > total_range.start.row) {
1390 length = num_cols;
1391 this_clines = clines;
1392 for (col = total_range.start.col; col <= total_range.end.col; col++) {
1393 needs_hline = latex2e_find_hhlines (this_clines, length, col,
1394 row - 1, current_sheet,
1395 MSTYLE_BORDER_BOTTOM)
1396 || needs_hline;
1397 this_clines ++;
1398 length--;
1401 /* We also need to know vertical borders */
1402 /* We do this here rather than as we output the cells since */
1403 /* we need to know the right connectors! */
1404 prev_vert = next_vert;
1405 next_vert = g_new0 (GnmStyleBorderType, num_cols + 1);
1406 this_vert = next_vert;
1407 *this_vert = latex2e_find_vline (total_range.start.col, row,
1408 current_sheet, MSTYLE_BORDER_LEFT);
1409 this_vert++;
1410 for (col = total_range.start.col; col <= total_range.end.col; col++) {
1411 *this_vert = latex2e_find_vline (col, row, current_sheet,
1412 MSTYLE_BORDER_RIGHT);
1413 this_vert ++;
1416 if (needs_hline)
1417 latex2e_print_hhline (output, clines, num_cols, prev_vert, next_vert);
1418 g_free (clines);
1420 for (col = total_range.start.col; col <= total_range.end.col; col++) {
1421 GnmCellPos pos;
1423 pos.col = col;
1424 pos.row = row;
1426 /* Get the cell. */
1427 cell = sheet_cell_get (current_sheet, col, row);
1429 /* Check if we are not the first cell in the row.*/
1430 if (col != total_range.start.col)
1431 gsf_output_printf (output, "\t&");
1432 else
1433 gsf_output_printf (output, "\t ");
1435 /* Check a merge. */
1436 merge_range = gnm_sheet_merge_is_corner (current_sheet, &pos);
1437 if (merge_range == NULL) {
1438 if (gnm_cell_is_empty(cell))
1439 latex2e_write_blank_multicolumn_cell(output, col, row,
1440 1, 1,
1441 col - total_range.start.col,
1442 next_vert, current_sheet);
1443 else
1444 latex2e_write_multicolumn_cell(output, cell, col,
1445 1, 1,
1446 col - total_range.start.col,
1447 next_vert, current_sheet);
1448 continue;
1451 /* Get the extent of the merge. */
1452 num_merged_cols = merge_range->end.col - merge_range->start.col + 1;
1453 num_merged_rows = merge_range->end.row - merge_range->start.row + 1;
1455 if (gnm_cell_is_empty(cell))
1456 latex2e_write_blank_multicolumn_cell(output, col, row,
1457 num_merged_cols,
1458 num_merged_rows,
1459 col - total_range.start.col,
1460 next_vert, current_sheet);
1461 else
1462 latex2e_write_multicolumn_cell(output, cell, col, num_merged_cols,
1463 num_merged_rows,
1464 col - total_range.start.col,
1465 next_vert, current_sheet);
1466 col += (num_merged_cols - 1);
1467 continue;
1469 gsf_output_printf (output, "\\\\\n");
1470 g_free (prev_vert);
1473 /* We need to check for horizontal borders at the bottom of the last row */
1474 clines = g_new0 (GnmStyleBorderType, total_range.end.col - total_range.start.col + 1);
1475 needs_hline = FALSE;
1476 /* In case that we are at the very bottom of the sheet we can not */
1477 /* check on the next line! */
1478 if (row < colrow_max (FALSE, current_sheet)) {
1479 length = num_cols;
1480 this_clines = clines;
1481 for (col = total_range.start.col; col <= total_range.end.col; col++) {
1482 needs_hline = latex2e_find_hhlines (this_clines, length, col, row,
1483 current_sheet, MSTYLE_BORDER_TOP)
1484 || needs_hline;
1485 this_clines ++;
1486 length--;
1489 length = num_cols;
1490 this_clines = clines;
1491 for (col = total_range.start.col; col <= total_range.end.col; col++) {
1492 needs_hline = latex2e_find_hhlines (this_clines, length, col,
1493 row - 1, current_sheet,
1494 MSTYLE_BORDER_BOTTOM)
1495 || needs_hline;
1496 this_clines ++;
1497 length--;
1499 if (needs_hline)
1500 latex2e_print_hhline (output, clines, num_cols, next_vert, NULL);
1501 g_free (clines);
1503 g_free (next_vert);
1505 gsf_output_puts (output, "\\end{longtable}\n\n"
1506 "\\ifthenelse{\\isundefined{\\languageshorthands}}"
1507 "{}{\\languageshorthands{\\languagename}}\n"
1508 "\\gnumericTableEnd\n");
1513 * latex2e_table_cell:
1515 * @output: output stream where the cell contents will be written.
1516 * @cell: the cell whose contents are to be written.
1518 * This function creates all the LaTeX code for the cell of a table (i.e. all
1519 * the code that might fall between two ampersands (&)).
1522 static void
1523 latex2e_table_write_cell (GsfOutput *output, GnmCell *cell)
1525 GnmStyle const *style = gnm_cell_get_style (cell);
1527 if (gnm_style_get_contents_hidden (style))
1528 return;
1530 if (!gnm_cell_is_empty (cell)) {
1531 char * rendered_string;
1533 rendered_string = gnm_cell_get_rendered_text (cell);
1534 latex_fputs (rendered_string, output);
1535 g_free (rendered_string);
1541 * latex2e_table_write_file_header:
1543 * @output: Output stream where the cell contents will be written.
1545 * This ouputs the LaTeX header. Kept separate for esthetics.
1548 static void
1549 latex2e_table_write_file_header(GsfOutput *output)
1551 gsf_output_puts (output,
1552 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
1553 "%% %%\n"
1554 "%% This is a LaTeX2e table fragment exported from Gnumeric. %%\n"
1555 "%% %%\n"
1556 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
1561 * latex_table_file_save_impl : The LaTeX2e exporter plugin function.
1563 * @WorkbookView: this provides the way to access the sheet being exported.
1564 * @outpu: where we'll write.
1565 * @all: Whether to write all rows or just the visible ones.
1567 * This writes the top sheet of a Gnumeric workbook as the content of a latex table environment.
1568 * We try to avoid all formatting.
1570 static void
1571 latex_table_file_save_impl (WorkbookView const *wb_view, GsfOutput *output, gboolean all)
1573 Workbook *wb = wb_view_get_workbook (wb_view);
1574 GnmCell *cell;
1575 Sheet *current_sheet;
1576 GnmRange total_range;
1577 int row, col;
1578 GPtrArray *sel;
1580 /* This is the preamble of the LaTeX2e file. */
1581 latex2e_table_write_file_header(output);
1583 /* Get the sheet and its range from the plugin function argument. */
1584 sel = g_object_get_data (G_OBJECT (wb), SHEET_SELECTION_KEY);
1585 current_sheet = sel && sel->len
1586 ? g_ptr_array_index (sel, 0)
1587 : wb_view_cur_sheet(wb_view);
1588 total_range = file_saver_sheet_get_extent (current_sheet);
1590 /* Step through the sheet, writing cells as appropriate. */
1591 for (row = total_range.start.row; row <= total_range.end.row; row++) {
1592 ColRowInfo const * ri;
1593 ri = sheet_row_get_info (current_sheet, row);
1594 if (all || ri->visible) {
1595 if (ri->needs_respan)
1596 row_calc_spans ((ColRowInfo *) ri, row, current_sheet);
1598 for (col = total_range.start.col; col <= total_range.end.col; col++) {
1599 /* Get the cell. */
1600 cell = sheet_cell_get (current_sheet, col, row);
1602 /* Check if we are not the first cell in the row.*/
1603 if (col != total_range.start.col)
1604 gsf_output_printf (output, "\t&");
1606 if (gnm_cell_is_empty (cell))
1607 continue;
1609 latex2e_table_write_cell(output, cell);
1611 gsf_output_printf (output, "\\\\\n");
1617 * latex_table_file_save : The LaTeX2e exporter plugin function.
1619 * @FileSaver: New structure for file plugins. I don't understand.
1620 * @IOcontext: currently not used but reserved for the future.
1621 * @WorkbookView: this provides the way to access the sheet being exported.
1622 * @output: where we'll write.
1624 * This writes the selected sheet of a Gnumeric workbook as the content of a
1625 * latex table environment. We try to avoid all formatting.
1627 void
1628 latex_table_file_save (G_GNUC_UNUSED GOFileSaver const *fs,
1629 G_GNUC_UNUSED GOIOContext *io_context,
1630 WorkbookView const *wb_view, GsfOutput *output)
1632 latex_table_file_save_impl (wb_view, output, TRUE);
1636 * latex_table_visible_file_save : The LaTeX2e exporter plugin function.
1638 * @FileSaver: New structure for file plugins. I don't understand.
1639 * @IOcontext: currently not used but reserved for the future.
1640 * @WorkbookView: this provides the way to access the sheet being exported.
1641 * @output: where we'll write.
1643 * This writes the selected sheet of a Gnumeric workbook as the content of a
1644 * latex table environment. We try to avoid all formatting.
1646 void
1647 latex_table_visible_file_save (G_GNUC_UNUSED GOFileSaver const *fs,
1648 G_GNUC_UNUSED GOIOContext *io_context,
1649 WorkbookView const *wb_view, GsfOutput *output)
1651 latex_table_file_save_impl (wb_view, output, FALSE);