1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
5 * Copyright (C) 1999, 2000 Rasca, Berlin
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:
35 * latex_table_visible_file_save()
36 * latex_table_file_save
41 #include <gnumeric-config.h>
43 #include <gnumeric-conf.h>
45 #include <goffice/goffice.h>
46 #include <workbook-view.h>
49 #include <sheet-merge.h>
51 #include <style-color.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>
60 #include <print-info.h>
63 #include <gsf/gsf-output.h>
68 LATEX_SINGLE_BORDER
= 1,
69 LATEX_DOUBLE_BORDER
= 2,
76 char const *horizontal
;
77 } latex_border_translator_t
;
79 /* the index into the following array is GnmStyleBorderType */
80 static latex_border_translator_t
const border_styles
[] = {
81 {LATEX_NO_BORDER
, "", "~"},
82 {LATEX_SINGLE_BORDER
, "|", "-"},
83 {LATEX_SINGLE_BORDER
, "|", "-"},
84 {LATEX_SINGLE_BORDER
, "|", "-"},
85 {LATEX_SINGLE_BORDER
, "|", "-"},
86 {LATEX_DOUBLE_BORDER
, "||","="},
87 {LATEX_DOUBLE_BORDER
, "||","="},
88 {LATEX_SINGLE_BORDER
, "|", "-"},
89 {LATEX_SINGLE_BORDER
, "|", "-"},
90 {LATEX_SINGLE_BORDER
, "|", "-"},
91 {LATEX_SINGLE_BORDER
, "|", "-"},
92 {LATEX_SINGLE_BORDER
, "|", "-"},
93 {LATEX_SINGLE_BORDER
, "|", "-"},
94 {LATEX_NO_BORDER
, "", ""}
100 } latex_border_connectors_t
;
103 static latex_border_connectors_t
const conn_styles
[LATEX_MAX_BORDER
]
104 [LATEX_MAX_BORDER
][LATEX_MAX_BORDER
][LATEX_MAX_BORDER
] = {
105 /* FIXME: once we are sure that none of the numbered */
106 /*entries are in fact needed we should removed the digits */
107 {{{{"",""}, { "",""}, { "",""}},
108 {{"",""}, { "|",""}, { "32",""}},
109 {{"",""}, { "11",""}, { "","|t:"}}},
110 {{{"",""}, { "",""}, { "",""}},
111 {{"","|"}, { "|",""}, { "33",""}},
112 {{"1",""}, { "13",""}, { "34",""}}},
113 {{{"",""}, { "",""}, { "|","|"}},
114 {{"","|b|"}, { "14",""}, { "|","|"}},
115 {{"","|b:"}, { "|b:",""}, { "|",":"}}}},
116 {{{{"",""}, { "",""}, { "",""}},
117 {{"",""}, { "|",""}, { "35",""}},
118 {{"","|"}, { "17",""}, { "36",""}}},
119 {{{"","|"}, { "|",""}, { "37",""}},
120 {{"|",""}, { "",""}, { "38",""}},
121 {{"4",""}, { "19",""}, { "39",""}}},
122 {{{"","|b|"}, { "20",""}, { "|","|"}},
123 {{"5",""}, { "21",""}, { "|","|"}},
124 {{"|b:",""}, { "22",""}, { "40",""}}}},
125 {{{{"",""}, { "23",""}, { ":t|",""}},
126 {{"|",""}, { "24",""}, { ":t|",""}},
127 {{"",""}, { "",""}, { ":t:",""}}},
128 {{{"7",""}, { "26",""}, { ":t|",""}},
129 {{"8",""}, { "27",""}, { "43",""}},
130 {{"",""}, { "",""}, { ":t:",""}}},
131 {{{":b|",""}, { "29",""}, { ":","|"}},
132 {{":b|",""}, { "30",""}, { ":|",""}},
133 {{":b:",""}, { ":b:",""}, { ":",":"}}}}
138 * @p: a pointer to a char, start of the string to be processed
139 * @output: output stream where the processed characters are written.
140 * @utf8: is this a utf8 string?
143 * If @p is in form of \L{foo}, return the char pointer pointing to '}' of \L{foo}
144 * else return @p untouched;
146 * Check if @p is in form of \L{foo}.
147 * If it is, the exact "foo" will be put into @output, without any esacaping.
151 latex_raw_str(char const *p
, GsfOutput
*output
, gboolean utf8
)
153 char const *p_begin
, *p_orig
= p
;
155 if(strncasecmp(p
, "\\L{", 3) == 0){
158 /* find the matching close bracket */
159 for(; *p
; p
= utf8
? g_utf8_next_char(p
) : p
+ 1){
160 switch(*p
){ /* FIXME: how to put in unmatched brackets? */
167 /* put the string beginning from p_begin to p to output */
168 gsf_output_write(output
, p
- p_begin
, p_begin
);
181 * @p: a pointer to a char, start of the string to be processed.
182 * @output: output stream where the processed characters are written.
184 * This escapes any special LaTeX characters from the LaTeX engine,
185 * except the ones enclosed in "\L{" and "}".
186 * Re-ordered from Rasca's code to have most common first.
189 latex_fputs_utf (char const *p
, GsfOutput
*output
)
192 for (; *p
; p
= g_utf8_next_char (p
)) {
193 switch (g_utf8_get_char (p
)) {
195 /* These are the classic TeX symbols $ & % # _ { } (see Lamport, p.15) */
196 case '$': case '&': case '%': case '#':
197 case '_': case '{': case '}':
198 gsf_output_printf (output
, "\\%c", *p
);
200 /* These are the other special characters ~ ^ \ (see Lamport, p.15) */
202 gsf_output_printf (output
, "\\%c{ }", *p
);
205 rlt
= latex_raw_str(p
, output
, TRUE
);
207 gsf_output_puts (output
, "$\\backslash$");
211 /* Are these available only in LaTeX through mathmode? */
213 gsf_output_printf (output
, "$%c$", *p
);
217 gsf_output_write (output
,
218 (g_utf8_next_char (p
)) - p
, p
);
225 * latex_math_fputs_utf :
227 * @p: a pointer to a char, start of the string to be processed.
228 * @output: output stream where the processed characters are written.
230 * This escapes any special LaTeX characters from the LaTeX engine,
231 * except the ones enclosed in "\L{" and "}".
233 * We assume that htis will be set in Mathematics mode.
236 latex_math_fputs_utf (char const *p
, GsfOutput
*output
)
239 for (; *p
; p
= g_utf8_next_char (p
)) {
240 switch (g_utf8_get_char (p
)) {
242 /* These are the classic TeX symbols $ & % # (see Lamport, p.15) */
243 case '$': case '&': case '%': case '#':
244 gsf_output_printf (output
, "\\%c", *p
);
246 /* These are the other special characters ~ (see Lamport, p.15) */
248 gsf_output_printf (output
, "\\%c{ }", *p
);
251 rlt
= latex_raw_str(p
, output
, TRUE
);
253 gsf_output_puts (output
, "$\\backslash$");
258 gsf_output_write (output
,
259 (g_utf8_next_char (p
)) - p
, p
);
266 * latex_convert_latin_to_utf
268 * @text: string to convert
270 * return value needs to be freed with g_free
272 * call g_convert_with_fallback and also handle utf minus.
276 latex_convert_latin_to_utf (char const *text
)
278 char * encoded_text
= NULL
;
283 if (g_utf8_strchr (text
,-1, 0x2212) == NULL
) {
284 encoded_text
= g_convert_with_fallback
285 (text
, strlen (text
),
286 "ISO-8859-1", "UTF-8", (gchar
*)"?",
287 &bytes_read
, &bytes_written
, NULL
);
289 gunichar
* ucs_string
= NULL
;
290 gunichar
* this_unichar
;
295 ucs_string
= g_utf8_to_ucs4_fast (text
, -1, &items_written
);
296 for (this_unichar
= ucs_string
; *this_unichar
!= '\0'; this_unichar
++) {
297 if (*this_unichar
== 0x2212)
298 *this_unichar
= 0x002d;
300 new_text
= g_ucs4_to_utf8 (ucs_string
, -1, &items_read
, &items_written
, NULL
);
302 encoded_text
= g_convert_with_fallback
303 (new_text
, strlen (new_text
),
304 "ISO-8859-1", "UTF-8", (gchar
*)"?",
305 &bytes_read
, &bytes_written
, NULL
);
313 * latex_fputs_latin :
315 * @p: a pointer to a char, start of the string to be processed.
316 * @output: output stream where the processed characters are written.
318 * This escapes any special LaTeX characters from the LaTeX engine,
319 * except the ones enclosed in "\L{" and "}".
320 * Re-ordered from Rasca's code to have most common first.
323 latex_fputs_latin (char const *text
, GsfOutput
*output
)
325 char * encoded_text
= NULL
;
329 encoded_text
= latex_convert_latin_to_utf (text
);
331 for (p
= encoded_text
; *p
; p
++) {
334 /* These are the classic TeX symbols $ & % # _ { } (see Lamport, p.15) */
335 case '$': case '&': case '%': case '#':
336 case '_': case '{': case '}':
337 gsf_output_printf (output
, "\\%c", *p
);
339 /* These are the other special characters ~ ^ \ (see Lamport, p.15) */
341 gsf_output_printf (output
, "\\%c{ }", *p
);
344 rlt
= latex_raw_str(p
, output
, FALSE
);
346 gsf_output_puts (output
, "$\\backslash$");
350 /* Are these available only in LaTeX through mathmode? */
351 case '>': case '<': case 'µ':
352 gsf_output_printf (output
, "$%c$", *p
);
356 gsf_output_write (output
, 1, p
);
360 g_free (encoded_text
);
364 * latex_math_fputs_latin :
366 * @p: a pointer to a char, start of the string to be processed.
367 * @output: output stream where the processed characters are written.
369 * This escapes any special LaTeX characters from the LaTeX engine,
370 * except the ones enclosed in "\L{" and "}".
372 * We assume that htis will be set in Mathematics mode.
375 latex_math_fputs_latin (char const *text
, GsfOutput
*output
)
377 char * encoded_text
= NULL
;
381 encoded_text
= latex_convert_latin_to_utf (text
);
383 for (p
= encoded_text
; *p
; p
++) {
386 /* These are the classic TeX symbols $ & % # (see Lamport, p.15) */
387 case '$': case '&': case '%': case '#':
388 gsf_output_printf (output
, "\\%c", *p
);
390 /* These are the other special characters ~ (see Lamport, p.15) */
392 gsf_output_printf (output
, "\\%c{ }", *p
);
395 rlt
= latex_raw_str(p
, output
, FALSE
);
397 gsf_output_puts (output
, "$\\backslash$");
403 gsf_output_write (output
, 1, p
);
407 g_free (encoded_text
);
411 latex_fputs (char const *text
, GsfOutput
*output
)
413 if (gnm_conf_get_plugin_latex_use_utf8 ())
414 latex_fputs_utf (text
, output
);
416 latex_fputs_latin (text
, output
);
420 latex_math_fputs (char const *text
, GsfOutput
*output
)
422 if (gnm_conf_get_plugin_latex_use_utf8 ())
423 latex_math_fputs_utf (text
, output
);
425 latex_math_fputs_latin (text
, output
);
429 cb_find_font_encodings (GnmCellIter
const *iter
, gboolean
*fonts
)
431 GnmCell
*cell
= iter
->cell
;
434 gnm_rendered_value_get_text
435 (gnm_cell_fetch_rendered_value (cell
, TRUE
));
437 gunichar ch
= g_utf8_get_char (rs
);
438 GUnicodeScript script
= g_unichar_get_script (ch
);
439 if (script
> 0 && script
<= G_UNICODE_SCRIPT_MANDAIC
)
441 rs
= g_utf8_next_char (rs
);
448 * latex2e_write_font_encodings writes
449 * \usepackage[T2A]{fontenc}
450 * in the presence of cyrillic text
454 latex2e_write_font_encodings (GsfOutput
*output
, Sheet
*sheet
, GnmRange
const *range
)
456 gboolean
*fonts
= g_new0 (gboolean
, G_UNICODE_SCRIPT_MANDAIC
+ 1);
458 sheet_foreach_cell_in_range
459 (sheet
, CELL_ITER_IGNORE_BLANK
| CELL_ITER_IGNORE_HIDDEN
, range
,
460 (CellIterFunc
)&cb_find_font_encodings
, fonts
);
462 if (fonts
[G_UNICODE_SCRIPT_CYRILLIC
])
463 gsf_output_puts (output
,
464 " \\usepackage[T2A]{fontenc}\n"
469 * latex2e_write_file_header:
471 * @output: Output stream where the cell contents will be written.
473 * This ouputs the LaTeX header. Kept separate for esthetics.
477 latex2e_write_file_header(GsfOutput
*output
, Sheet
*sheet
, GnmRange
const *range
)
479 gboolean is_landscape
= FALSE
, use_utf8
;
480 GtkPageOrientation orient
= print_info_get_paper_orientation (sheet
->print_info
);
482 is_landscape
= (orient
== GTK_PAGE_ORIENTATION_LANDSCAPE
||
483 orient
== GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE
);
484 use_utf8
= gnm_conf_get_plugin_latex_use_utf8 ();
486 gsf_output_puts (output
,
487 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
489 "%% This is the header of a LaTeX2e file exported from Gnumeric. %%\n"
491 "%% This file can be compiled as it stands or included in another %%\n"
492 "%% LaTeX document. The table is based on the longtable package so %%\n"
493 "%% the longtable options (headers, footers...) can be set in the %%\n"
494 "%% preamble section below (see PRAMBLE). %%\n"
496 "%% To include the file in another, the following two lines must be %%\n"
497 "%% in the including file: %%\n"
498 "%% \\def\\inputGnumericTable{} %%\n"
499 "%% at the beginning of the file and: %%\n"
500 "%% \\input{name-of-this-file.tex} %%\n"
501 "%% where the table is to be placed. Note also that the including %%\n"
502 "%% file must use the following packages for the table to be %%\n"
503 "%% rendered correctly: %%\n"
507 gsf_output_puts (output
,
508 "%% \\usepackage{ucs} %%\n"
509 "%% \\usepackage[utf8x]{inputenc} %%\n"
510 "%% \\usepackage[T2A]{fontenc} % if cyrillic is used %%\n"
513 gsf_output_puts (output
,
514 "%% \\usepackage[latin1]{inputenc} %%\n"
517 gsf_output_puts (output
,
518 "%% \\usepackage{color} %%\n"
519 "%% \\usepackage{array} %%\n"
520 "%% \\usepackage{longtable} %%\n"
521 "%% \\usepackage{calc} %%\n"
522 "%% \\usepackage{multirow} %%\n"
523 "%% \\usepackage{hhline} %%\n"
524 "%% \\usepackage{ifthen} %%\n"
525 "%% optionally (for landscape tables embedded in another document): %%\n"
526 "%% \\usepackage{lscape} %%\n"
528 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
532 "%% This section checks if we are begin input into another file or %%\n"
533 "%% the file will be compiled alone. First use a macro taken from %%\n"
534 "%% the TeXbook ex 7.7 (suggestion of Han-Wen Nienhuys). %%\n"
535 "\\def\\ifundefined#1{\\expandafter\\ifx\\csname#1\\endcsname\\relax}\n"
538 "%% Check for the \\def token for inputed files. If it is not %%\n"
539 "%% defined, the file will be processed as a standalone and the %%\n"
540 "%% preamble will be used. %%\n"
541 "\\ifundefined{inputGnumericTable}\n"
543 "%% We must be able to close or not the document at the end. %%\n"
544 " \\def\\gnumericTableEnd{\\end{document}}\n"
547 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
549 "%% This is the PREAMBLE. Change these values to get the right %%\n"
550 "%% paper size and other niceties. %%\n"
552 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
556 gsf_output_puts (output
,
557 " \\documentclass[12pt%\n"
562 gsf_output_puts (output
,
563 " \\documentclass[12pt%\n"
570 if (gnm_conf_get_plugin_latex_use_utf8 ()) {
571 gsf_output_puts (output
,
572 " \\usepackage{ucs}\n"
573 " \\usepackage[utf8x]{inputenc}\n"
575 latex2e_write_font_encodings (output
, sheet
, range
);
577 gsf_output_puts (output
,
578 " \\usepackage[latin1]{inputenc}\n"
581 gsf_output_puts (output
,
582 " \\usepackage{fullpage}\n"
583 " \\usepackage{color}\n"
584 " \\usepackage{array}\n"
585 " \\usepackage{longtable}\n"
586 " \\usepackage{calc}\n"
587 " \\usepackage{multirow}\n"
588 " \\usepackage{hhline}\n"
589 " \\usepackage{ifthen}\n"
591 " \\begin{document}\n"
594 "%% End of the preamble for the standalone. The next section is for %%\n"
595 "%% documents which are included into other LaTeX2e files. %%\n"
598 "%% We are not a stand alone document. For a regular table, we will %%\n"
599 "%% have no preamble and only define the closing to mean nothing. %%\n"
600 " \\def\\gnumericTableEnd{}\n"
602 "%% If we want landscape mode in an embedded document, comment out %%\n"
603 "%% the line above and uncomment the two below. The table will %%\n"
604 "%% begin on a new page and run in landscape mode. %%\n"
605 "% \\def\\gnumericTableEnd{\\end{landscape}}\n"
606 "% \\begin{landscape}\n"
609 "%% End of the else clause for this file being \\input. %%\n"
612 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
614 "%% The rest is the gnumeric table, except for the closing %%\n"
615 "%% statement. Changes below will alter the table\'s appearance. %%\n"
617 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
619 "\\providecommand{\\gnumericmathit}[1]{#1} \n"
620 "%% Uncomment the next line if you would like your numbers to be in %%\n"
621 "%% italics if they are italizised in the gnumeric table. %%\n"
622 "%\\renewcommand{\\gnumericmathit}[1]{\\mathit{#1}}\n"
623 "\\providecommand{\\gnumericPB}[1]%\n"
624 "{\\let\\gnumericTemp=\\\\#1\\let\\\\=\\gnumericTemp\\hspace{0pt}}\n"
625 " \\ifundefined{gnumericTableWidthDefined}\n"
626 " \\newlength{\\gnumericTableWidth}\n"
627 " \\newlength{\\gnumericTableWidthComplete}\n"
628 " \\newlength{\\gnumericMultiRowLength}\n"
629 " \\global\\def\\gnumericTableWidthDefined{}\n"
631 "%% The following setting protects this code from babel shorthands. %%\n"
632 " \\ifthenelse{\\isundefined{\\languageshorthands}}{}{\\languageshorthands{english}}"
634 "%% The default table format retains the relative column widths of %%\n"
635 "%% gnumeric. They can easily be changed to c, r or l. In that case %%\n"
636 "%% you may want to comment out the next line and uncomment the one %%\n"
638 "\\providecommand\\gnumbox{\\makebox[0pt]}\n"
639 "%%\\providecommand\\gnumbox[1][]{\\makebox}\n"
641 "%% to adjust positions in multirow situations %%\n"
642 "\\setlength{\\bigstrutjot}{\\jot}\n"
643 "\\setlength{\\extrarowheight}{\\doublerulesep}\n"
645 "%% The \\setlongtables command keeps column widths the same across %%\n"
646 "%% pages. Simply comment out next line for varying column widths. %%\n"
654 * latex2e_write_table_header:
656 * @output: Output stream where the cell contents will be written.
657 * @num_cols: The number of columns in the table
659 * A convenience function that also helps make nicer code.
662 latex2e_write_table_header(GsfOutput
*output
, int num_cols
)
667 gsf_output_puts (output
,
668 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
669 "%% The longtable options. (Caption, headers... see Goosens, p.124) %%\n"
670 "%\t\\caption{The Table Caption.} \\\\ %\n"
671 "% \\hline % Across the top of the table.\n"
672 "%% The rest of these options are table rows which are placed on %%\n"
673 "%% the first, last or every page. Use \\multicolumn if you want. %%\n"
675 "%% Header for the first page. %%\n"
678 gsf_output_printf (output
, "%%\t\\multicolumn{%d}{c}{The First Header} \\\\ \\hline \n", num_cols
);
679 gsf_output_printf (output
, "%%\t\\multicolumn{1}{c}{colTag}\t%%Column 1\n");
680 for (col
= 2 ; col
< num_cols
; col
++)
681 gsf_output_printf (output
, "%%\t&\\multicolumn{1}{c}{colTag}\t%%Column %d\n",col
);
682 gsf_output_printf (output
, "%%\t&\\multicolumn{1}{c}{colTag}\t\\\\ \\hline %%Last column\n");
683 gsf_output_printf (output
, "%%\t\\endfirsthead\n\n");
685 gsf_output_printf (output
, "%%%% The running header definition. %%%%\n");
686 gsf_output_printf (output
, "%%\t\\hline\n");
687 gsf_output_printf (output
, "%%\t\\multicolumn{%d}{l}{\\ldots\\small\\slshape continued} \\\\ \\hline\n", num_cols
);
688 gsf_output_printf (output
, "%%\t\\multicolumn{1}{c}{colTag}\t%%Column 1\n");
689 for (col
= 2 ; col
< num_cols
; col
++)
690 gsf_output_printf (output
, "%%\t&\\multicolumn{1}{c}{colTag}\t%%Column %d\n",col
);
691 gsf_output_printf (output
, "%%\t&\\multicolumn{1}{c}{colTag}\t\\\\ \\hline %%Last column\n");
692 gsf_output_printf (output
, "%%\t\\endhead\n\n");
694 gsf_output_printf (output
, "%%%% The running footer definition. %%%%\n");
695 gsf_output_printf (output
, "%%\t\\hline\n");
696 gsf_output_printf (output
, "%%\t\\multicolumn{%d}{r}{\\small\\slshape continued\\ldots}", num_cols
);
697 gsf_output_printf (output
, " \\\\\n");
698 gsf_output_printf (output
, "%%\t\\endfoot\n\n");
700 gsf_output_printf (output
, "%%%% The ending footer definition. %%%%\n");
701 gsf_output_printf (output
, "%%\t\\multicolumn{%d}{c}{That's all folks} \\\\ \\hline \n", num_cols
);
702 gsf_output_printf (output
, "%%\t\\endlastfoot\n");
703 gsf_output_puts (output
, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n");
708 * latex2e_find_vline:
713 * @which_border: GnmStyleElement (MSTYLE_BORDER_LEFT or MSTYLE_BORDER_RIGHT)
715 * Determine the border style
718 static GnmStyleBorderType
719 latex2e_find_this_vline (int col
, int row
, Sheet
*sheet
, GnmStyleElement which_border
)
721 GnmBorder
const *border
;
722 GnmStyle
const *style
;
724 if (col
< 0 || row
< 0)
725 return GNM_STYLE_BORDER_NONE
;
727 style
= sheet_style_get (sheet
, col
, row
);
728 border
= gnm_style_get_border (style
, which_border
);
730 if (!gnm_style_border_is_blank (border
))
731 return border
->line_type
;
733 if (which_border
== MSTYLE_BORDER_LEFT
) {
735 return GNM_STYLE_BORDER_NONE
;
736 style
= sheet_style_get (sheet
, col
- 1, row
);
737 border
= gnm_style_get_border (style
, MSTYLE_BORDER_RIGHT
);
738 return ((border
== NULL
) ? GNM_STYLE_BORDER_NONE
: border
->line_type
);
740 if ((col
+1) >= colrow_max (TRUE
, sheet
))
741 return GNM_STYLE_BORDER_NONE
;
742 style
= sheet_style_get (sheet
, col
+ 1, row
);
743 border
= gnm_style_get_border (style
, MSTYLE_BORDER_LEFT
);
744 return ((border
== NULL
) ? GNM_STYLE_BORDER_NONE
: border
->line_type
);
747 return GNM_STYLE_BORDER_NONE
;
750 static GnmStyleBorderType
751 latex2e_find_vline (int col
, int row
, Sheet
*sheet
, GnmStyleElement which_border
)
753 /* We are checking for NONE boreders first since there should only be a few merged ranges */
754 GnmStyleBorderType result
= latex2e_find_this_vline (col
, row
, sheet
, which_border
);
756 GnmRange
const * range
;
758 if (result
== GNM_STYLE_BORDER_NONE
)
759 return GNM_STYLE_BORDER_NONE
;
763 range
= gnm_sheet_merge_contains_pos (sheet
, &pos
);
766 if ((which_border
== MSTYLE_BORDER_LEFT
&& col
== range
->start
.col
)
767 || (which_border
== MSTYLE_BORDER_RIGHT
&& col
== range
->end
.col
))
770 return GNM_STYLE_BORDER_NONE
;
776 * latex2e_print_vert_border:
778 * @output: Output stream where the cell contents will be written.
779 * @clines: GnmStyleBorderType indicating the type of border
783 latex2e_print_vert_border (GsfOutput
*output
, GnmStyleBorderType style
)
785 g_return_if_fail (/* style >= 0 && */ style
< G_N_ELEMENTS (border_styles
));
787 gsf_output_printf (output
, "%s", border_styles
[style
].vertical
);
791 * latex2e_write_blank_multicolumn_cell:
793 * @output: output stream where the cell contents will be written.
796 * @num_merged_cols: an integer value of the number of columns to merge.
797 * @num_merged_rows: an integer value of the number of rows to merge.
798 * @sheet: the current sheet.
800 * This function creates all the LaTeX code for the cell of a table (i.e. all
801 * the code that might fall between two ampersands (&)), assuming that
802 * the cell is in fact NULL. We therefore have only to worry about a few
807 latex2e_write_blank_multicolumn_cell (GsfOutput
*output
, int start_col
,
808 G_GNUC_UNUSED
int start_row
,
809 int num_merged_cols
, int num_merged_rows
,
811 GnmStyleBorderType
*borders
, Sheet
*sheet
)
814 GnmStyleBorderType left_border
= GNM_STYLE_BORDER_NONE
;
815 GnmStyleBorderType right_border
= GNM_STYLE_BORDER_NONE
;
817 if (num_merged_cols
> 1 || num_merged_rows
> 1) {
818 ColRowInfo
const * ci
;
821 for (i
= 0; i
< num_merged_cols
; i
++) {
822 ci
= sheet_col_get_info (sheet
, start_col
+ i
);
823 merge_width
+= ci
->size_pixels
;
828 left_border
= *borders
;
830 right_border
= borders
[index
+ num_merged_cols
];
832 /* We only set up a multicolumn command if necessary */
833 if (num_merged_cols
> 1) {
836 /* Open the multicolumn statement. */
837 gsf_output_printf (output
, "\\multicolumn{%d}{", num_merged_cols
);
839 if (left_border
!= GNM_STYLE_BORDER_NONE
)
840 latex2e_print_vert_border (output
, left_border
);
842 if (num_merged_rows
> 1) {
843 gsf_output_printf (output
, "c");
845 gsf_output_printf (output
, "p{");
846 for (i
= 0; i
< num_merged_cols
; i
++) {
847 gsf_output_printf (output
, "\t\\gnumericCol%s+%%\n",
848 col_name (start_col
+ i
));
850 gsf_output_printf (output
, "\t\\tabcolsep*2*%i}", num_merged_cols
- 1);
853 if (right_border
!= GNM_STYLE_BORDER_NONE
)
854 latex2e_print_vert_border (output
, right_border
);
856 /*Close the right delimiter, as above. Also open the text delimiter.*/
857 gsf_output_printf (output
,"}%%\n\t{");
858 } else if (left_border
!= GNM_STYLE_BORDER_NONE
|| right_border
!= GNM_STYLE_BORDER_NONE
) {
860 /* Open the multicolumn statement. */
861 gsf_output_printf (output
, "\\multicolumn{1}{");
863 if (left_border
!= GNM_STYLE_BORDER_NONE
)
864 latex2e_print_vert_border (output
, left_border
);
866 /* Drop in the left hand format delimiter. */
867 gsf_output_printf (output
, "p{\\gnumericCol%s}", col_name(start_col
));
869 if (right_border
!= GNM_STYLE_BORDER_NONE
)
870 latex2e_print_vert_border (output
, right_border
);
872 /*Close the right delimiter, as above. Also open the text delimiter.*/
873 gsf_output_printf (output
,"}%%\n\t{");
877 if (num_merged_rows
> 1) {
879 /* Open the multirow statement. */
880 gsf_output_printf (output
, "\\setlength{\\gnumericMultiRowLength}{0pt}%%\n");
881 for (i
= 0; i
< num_merged_cols
; i
++) {
882 gsf_output_printf (output
, "\t \\addtolength{\\gnumericMultiRowLength}{\\gnumericCol%s}%%\n", col_name (start_col
+ i
));
884 gsf_output_printf (output
, "\t \\addtolength{\\gnumericMultiRowLength}{\\tabcolsep}%%\n");
886 gsf_output_printf (output
, "\t \\multirow{%i}[%i]{\\gnumericMultiRowLength}{%%\n\t ", num_merged_rows
, num_merged_rows
/2);
888 /* Close the multirowtext. */
889 gsf_output_printf (output
, "}");
892 /* Close the multicolumn text bracket. */
893 if (num_merged_cols
> 1 || left_border
!= GNM_STYLE_BORDER_NONE
894 || right_border
!= GNM_STYLE_BORDER_NONE
)
895 gsf_output_printf (output
, "}");
897 /* And we are done. */
898 gsf_output_printf (output
, "\n");
904 * latex2e_write_multicolumn_cell:
906 * @output: output stream where the cell contents will be written.
907 * @cell: the cell whose contents are to be written.
909 * @num_merged_cols: an integer value of the number of columns to merge.
910 * @num_merged_rows: an integer value of the number of rows to merge.
911 * @sheet: the current sheet.
913 * This function creates all the LaTeX code for the cell of a table (i.e. all
914 * the code that might fall between two ampersands (&)).
916 * Note: we are _not_ putting single cell into \multicolumns since this
917 * makes it much more difficult to change column widths later on.
920 latex2e_write_multicolumn_cell (GsfOutput
*output
, GnmCell
*cell
, int start_col
,
921 int num_merged_cols
, int num_merged_rows
,
923 GnmStyleBorderType
*borders
, Sheet
*sheet
)
925 char * rendered_string
;
927 gboolean wrap
= FALSE
;
928 GOFormatFamily cell_format_family
;
930 GnmStyleBorderType left_border
= GNM_STYLE_BORDER_NONE
;
931 GnmStyleBorderType right_border
= GNM_STYLE_BORDER_NONE
;
933 /* Print the cell according to its style. */
934 GnmStyle
const *style
= gnm_cell_get_style (cell
);
935 gboolean hidden
= gnm_style_get_contents_hidden (style
);
937 g_return_if_fail (style
!= NULL
);
939 if (num_merged_cols
> 1 || num_merged_rows
> 1) {
940 ColRowInfo
const * ci
;
943 for (i
= 0; i
< num_merged_cols
; i
++) {
944 ci
= sheet_col_get_info (sheet
, start_col
+ i
);
945 merge_width
+= ci
->size_pixels
;
950 left_border
= *borders
;
952 right_border
= borders
[index
+ num_merged_cols
];
954 /* We only set up a multicolumn command if necessary */
955 if (num_merged_cols
> 1) {
958 /* Open the multicolumn statement. */
959 gsf_output_printf (output
, "\\multicolumn{%d}{", num_merged_cols
);
961 if (left_border
!= GNM_STYLE_BORDER_NONE
)
962 latex2e_print_vert_border (output
, left_border
);
964 if (num_merged_rows
> 1) {
965 gsf_output_printf (output
, "c");
967 gsf_output_printf (output
, "p{");
968 for (i
= 0; i
< num_merged_cols
; i
++) {
969 gsf_output_printf (output
, "\t\\gnumericCol%s+%%\n",
970 col_name (start_col
+ i
));
972 gsf_output_printf (output
, "\t\\tabcolsep*2*%i}", num_merged_cols
- 1);
975 if (right_border
!= GNM_STYLE_BORDER_NONE
)
976 latex2e_print_vert_border (output
, right_border
);
978 /*Close the right delimiter, as above. Also open the text delimiter.*/
979 gsf_output_printf (output
,"}%%\n\t{");
980 } else if (left_border
!= GNM_STYLE_BORDER_NONE
|| right_border
!= GNM_STYLE_BORDER_NONE
) {
982 /* Open the multicolumn statement. */
983 gsf_output_printf (output
, "\\multicolumn{1}{");
985 if (left_border
!= GNM_STYLE_BORDER_NONE
)
986 latex2e_print_vert_border (output
, left_border
);
988 /* Drop in the left hand format delimiter. */
989 gsf_output_printf (output
, "p{\\gnumericCol%s}", col_name(start_col
));
991 if (right_border
!= GNM_STYLE_BORDER_NONE
)
992 latex2e_print_vert_border (output
, right_border
);
994 /*Close the right delimiter, as above. Also open the text delimiter.*/
995 gsf_output_printf (output
,"}%%\n\t{");
999 if (num_merged_rows
> 1) {
1001 /* Open the multirow statement. */
1002 gsf_output_printf (output
, "\\setlength{\\gnumericMultiRowLength}{0pt}%%\n");
1003 for (i
= 0; i
< num_merged_cols
; i
++) {
1004 gsf_output_printf (output
, "\t \\addtolength{\\gnumericMultiRowLength}{\\gnumericCol%s}%%\n", col_name (start_col
+ i
));
1006 gsf_output_printf (output
, "\t \\addtolength{\\gnumericMultiRowLength}{\\tabcolsep}%%\n");
1008 gsf_output_printf (output
,
1009 "\t \\multirow{%i}[%i]{\\gnumericMultiRowLength}"
1010 "{\\parbox{\\gnumericMultiRowLength}{%%\n\t ",
1011 num_merged_rows
, num_merged_rows
/2);
1015 /* Send the alignment of the cell through a routine to deal with
1016 * GNM_HALIGN_GENERAL and then deal with the three cases. */
1017 switch (gnm_style_default_halign (style
, cell
)) {
1018 case GNM_HALIGN_RIGHT
:
1019 gsf_output_printf (output
, "\\gnumericPB{\\raggedleft}");
1021 case GNM_HALIGN_DISTRIBUTED
:
1022 case GNM_HALIGN_CENTER
:
1023 case GNM_HALIGN_CENTER_ACROSS_SELECTION
:
1024 gsf_output_printf (output
, "\\gnumericPB{\\centering}");
1026 case GNM_HALIGN_LEFT
:
1027 gsf_output_printf (output
, "\\gnumericPB{\\raggedright}");
1029 case GNM_HALIGN_JUSTIFY
:
1035 /* Check whether we should do word wrapping */
1036 wrap
= gnm_style_get_wrap_text (style
);
1038 /* if we don't wrap put it into an mbox, adjusted to width 0 to avoid moving */
1039 /* it to the second line of the parbox */
1041 switch (gnm_style_default_halign (style
, cell
)) {
1042 case GNM_HALIGN_RIGHT
:
1043 gsf_output_printf (output
, "\\gnumbox[r]{");
1045 case GNM_HALIGN_DISTRIBUTED
:
1046 case GNM_HALIGN_CENTER
:
1047 case GNM_HALIGN_CENTER_ACROSS_SELECTION
:
1048 gsf_output_printf (output
, "\\gnumbox{");
1050 case GNM_HALIGN_LEFT
:
1051 gsf_output_printf (output
, "\\gnumbox[l]{");
1053 case GNM_HALIGN_JUSTIFY
:
1054 gsf_output_printf (output
, "\\gnumbox[s]{");
1057 gsf_output_printf (output
, "\\makebox{");
1061 if (!gnm_cell_is_empty (cell
)) {
1062 /* Check the foreground (text) colour. */
1063 GOColor fore
= gnm_cell_get_render_color (cell
);
1067 r
= GO_COLOR_UINT_R (fore
);
1068 g
= GO_COLOR_UINT_G (fore
);
1069 b
= GO_COLOR_UINT_B (fore
);
1071 if (r
!= 0 || g
!= 0 || b
!= 0) {
1072 gchar buffer
[7] = {0};
1073 gsf_output_printf (output
, "{\\color[rgb]{");
1074 g_ascii_formatd (buffer
, 7, "%.2f",r
/255.0);
1075 gsf_output_printf (output
, "%s,", buffer
);
1076 g_ascii_formatd (buffer
, 7, "%.2f",g
/255.0);
1077 gsf_output_printf (output
, "%s,", buffer
);
1078 g_ascii_formatd (buffer
, 7, "%.2f",b
/255.0);
1079 gsf_output_printf (output
, "%s", buffer
);
1080 gsf_output_printf (output
, "} ");
1083 /* Establish the font's style for the styles that can be addressed by LaTeX.
1084 * More complicated efforts (like changing fonts) are left to the user.
1088 gsf_output_printf (output
, "\\phantom{");
1090 if (font_is_monospaced (style
))
1091 gsf_output_printf (output
, "\\texttt{");
1092 else if (font_is_sansserif (style
))
1093 gsf_output_printf (output
, "\\textsf{");
1094 if (gnm_style_get_font_bold (style
))
1095 gsf_output_printf (output
, "\\textbf{");
1096 if (gnm_style_get_font_italic (style
))
1097 gsf_output_printf (output
, "\\textit{");
1100 cell_format_family
= go_format_get_family (gnm_cell_get_format (cell
));
1101 if (cell_format_family
== GO_FORMAT_NUMBER
||
1102 cell_format_family
== GO_FORMAT_CURRENCY
||
1103 cell_format_family
== GO_FORMAT_PERCENTAGE
||
1104 cell_format_family
== GO_FORMAT_FRACTION
||
1105 cell_format_family
== GO_FORMAT_SCIENTIFIC
){
1106 gsf_output_printf (output
, "$");
1107 if (gnm_style_get_font_italic(style
))
1108 gsf_output_printf (output
, "\\gnumericmathit{");
1110 /* Print the cell contents. */
1111 rendered_string
= gnm_cell_get_rendered_text (cell
);
1112 latex_math_fputs (rendered_string
, output
);
1113 g_free (rendered_string
);
1115 if (gnm_style_get_font_italic(style
))
1116 gsf_output_printf (output
, "}");
1117 gsf_output_printf (output
, "$");
1119 /* Print the cell contents. */
1120 rendered_string
= gnm_cell_get_rendered_text (cell
);
1121 latex_fputs (rendered_string
, output
);
1122 g_free (rendered_string
);
1125 /* Close the styles for the cell. */
1126 if (gnm_style_get_font_italic (style
))
1127 gsf_output_printf (output
, "}");
1128 if (gnm_style_get_font_bold (style
))
1129 gsf_output_printf (output
, "}");
1130 if (font_is_monospaced (style
))
1131 gsf_output_printf (output
, "}");
1132 else if (font_is_sansserif (style
))
1133 gsf_output_printf (output
, "}");
1135 gsf_output_printf (output
, "}");
1136 if (r
!= 0 || g
!= 0 || b
!= 0)
1137 gsf_output_printf (output
, "}");
1140 /* if we don't wrap close the mbox */
1142 gsf_output_printf (output
, "}");
1144 /* Close the multirowtext. */
1145 if (num_merged_rows
> 1)
1146 gsf_output_printf (output
, "}}");
1148 /* Close the multicolumn text bracket. */
1149 if (num_merged_cols
> 1 || left_border
!= GNM_STYLE_BORDER_NONE
1150 || right_border
!= GNM_STYLE_BORDER_NONE
)
1151 gsf_output_printf (output
, "}");
1153 /* And we are done. */
1154 gsf_output_printf (output
, "\n");
1159 * latex2e_find_hhlines :
1161 * @clines: array of GnmStyleBorderType* indicating the type of border
1162 * @length: (remaining) positions in clines
1167 * Determine the border style
1172 latex2e_find_hhlines (GnmStyleBorderType
*clines
, G_GNUC_UNUSED
int length
, int col
, int row
,
1173 Sheet
*sheet
, GnmStyleElement type
)
1175 GnmStyle
const *style
;
1176 GnmBorder
const *border
;
1177 GnmRange
const *range
;
1180 style
= sheet_style_get (sheet
, col
, row
);
1181 border
= gnm_style_get_border (style
, type
);
1182 if (gnm_style_border_is_blank (border
))
1184 clines
[0] = border
->line_type
;
1188 range
= gnm_sheet_merge_contains_pos (sheet
, &pos
);
1190 if ((type
== MSTYLE_BORDER_TOP
&& row
> range
->start
.row
)
1191 || (type
== MSTYLE_BORDER_BOTTOM
&& row
< range
->end
.row
)) {
1192 clines
[0] = GNM_STYLE_BORDER_NONE
;
1202 * latex2e_print_hhline :
1204 * @output: output stream where the cell contents will be written.
1205 * @clines: an array of GnmStyleBorderType* indicating the type of border
1206 * @n: the number of elements in clines
1208 * This procedure prints an hhline command according to the content
1213 latex2e_print_hhline (GsfOutput
*output
, GnmStyleBorderType
*clines
, int n
, GnmStyleBorderType
*prev_vert
,
1214 GnmStyleBorderType
*next_vert
)
1217 gsf_output_printf (output
, "\\hhline{");
1218 gsf_output_printf (output
, "%s", conn_styles
[LATEX_NO_BORDER
]
1219 [prev_vert
? border_styles
[prev_vert
[0]].latex
: LATEX_NO_BORDER
]
1220 [border_styles
[clines
[0]].latex
]
1221 [next_vert
? border_styles
[next_vert
[0]].latex
: LATEX_NO_BORDER
].p_1
);
1222 gsf_output_printf (output
, "%s", conn_styles
[LATEX_NO_BORDER
]
1223 [prev_vert
? border_styles
[prev_vert
[0]].latex
: LATEX_NO_BORDER
]
1224 [border_styles
[clines
[0]].latex
]
1225 [next_vert
? border_styles
[next_vert
[0]].latex
: LATEX_NO_BORDER
].p_2
);
1226 for (col
= 0; col
< n
- 1; col
++) {
1227 gsf_output_printf (output
, "%s", border_styles
[clines
[col
]].horizontal
);
1228 gsf_output_printf (output
, "%s", conn_styles
[border_styles
[clines
[col
]].latex
]
1229 [prev_vert
? border_styles
[prev_vert
[col
+ 1]].latex
:
1231 [border_styles
[clines
[col
+1]].latex
]
1232 [next_vert
? border_styles
[next_vert
[col
+ 1]].latex
:
1233 LATEX_NO_BORDER
].p_1
);
1234 gsf_output_printf (output
, "%s", conn_styles
[border_styles
[clines
[col
]].latex
]
1235 [prev_vert
? border_styles
[prev_vert
[col
+ 1]].latex
:
1237 [border_styles
[clines
[col
+1]].latex
]
1238 [next_vert
? border_styles
[next_vert
[col
+ 1]].latex
:
1239 LATEX_NO_BORDER
].p_2
);
1241 gsf_output_printf (output
, "%s", border_styles
[clines
[n
- 1]].horizontal
);
1242 gsf_output_printf (output
, "%s", conn_styles
[border_styles
[clines
[n
- 1]].latex
]
1243 [prev_vert
? border_styles
[prev_vert
[n
]].latex
: LATEX_NO_BORDER
]
1245 [next_vert
? border_styles
[next_vert
[n
]].latex
:
1246 LATEX_NO_BORDER
].p_1
);
1247 gsf_output_printf (output
, "%s", conn_styles
[border_styles
[clines
[n
- 1]].latex
]
1248 [prev_vert
? border_styles
[prev_vert
[n
]].latex
: LATEX_NO_BORDER
]
1250 [next_vert
? border_styles
[next_vert
[n
]].latex
:
1251 LATEX_NO_BORDER
].p_2
);
1253 gsf_output_printf (output
, "}\n");
1257 file_saver_sheet_get_extent (Sheet
*sheet
)
1260 = g_object_get_data (G_OBJECT (sheet
->workbook
),
1263 Sheet
*start_sheet
, *end_sheet
;
1267 gnm_rangeref_normalize (range
,
1268 eval_pos_init_sheet (&ep
, sheet
),
1269 &start_sheet
, &end_sheet
,
1271 if (start_sheet
== sheet
)
1274 return sheet_get_extent (sheet
, TRUE
, TRUE
);
1278 * latex_file_save : The LaTeX2e exporter plugin function.
1280 * @FileSaver: New structure for file plugins. I don't understand.
1281 * @IOcontext: currently not used but reserved for the future.
1282 * @WorkbookView: this provides the way to access the sheet being exported.
1283 * @filename: where we'll write.
1285 * This writes the top sheet of a Gnumeric workbook to a LaTeX2e longtable. We
1286 * check for merges here, then call the function latex2e_write_multicolum_cell()
1287 * to render the format and contents of the cell.
1290 latex_file_save (G_GNUC_UNUSED GOFileSaver
const *fs
, G_GNUC_UNUSED GOIOContext
*io_context
,
1291 WorkbookView
const *wb_view
, GsfOutput
*output
)
1294 Sheet
*current_sheet
;
1295 GnmRange total_range
;
1296 GnmRange
const *merge_range
;
1297 int row
, col
, num_cols
, length
;
1298 int num_merged_cols
, num_merged_rows
;
1299 GnmStyleBorderType
*clines
, *this_clines
;
1300 GnmStyleBorderType
*prev_vert
= NULL
, *next_vert
= NULL
, *this_vert
;
1301 gboolean needs_hline
;
1303 /* Get the topmost sheet and its range from the plugin function argument. */
1304 current_sheet
= wb_view_cur_sheet(wb_view
);
1305 total_range
= file_saver_sheet_get_extent (current_sheet
);
1307 /* This is the preamble of the LaTeX2e file. */
1308 latex2e_write_file_header(output
, current_sheet
, &total_range
);
1310 num_cols
= total_range
.end
.col
- total_range
.start
.col
+ 1;
1312 gsf_output_printf (output
, "\\setlength\\gnumericTableWidth{%%\n");
1313 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
1314 ColRowInfo
const * ci
;
1315 ci
= sheet_col_get_info (current_sheet
, col
);
1316 gsf_output_printf (output
, "\t%ipt+%%\n", ci
->size_pixels
* 10 / 12);
1318 gsf_output_printf (output
, "0pt}\n\\def\\gumericNumCols{%i}\n", num_cols
);
1320 gsf_output_puts (output
, ""
1321 "\\setlength\\gnumericTableWidthComplete{\\gnumericTableWidth+%\n"
1322 " \\tabcolsep*\\gumericNumCols*2+\\arrayrulewidth*\\gumericNumCols}\n"
1323 "\\ifthenelse{\\lengthtest{\\gnumericTableWidthComplete > \\linewidth}}%\n"
1324 " {\\def\\gnumericScale{\\ratio{\\linewidth-%\n"
1325 " \\tabcolsep*\\gumericNumCols*2-%\n"
1326 " \\arrayrulewidth*\\gumericNumCols}%\n"
1327 "{\\gnumericTableWidth}}}%\n"
1328 "{\\def\\gnumericScale{1}}\n"
1330 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
1332 "%% The following are the widths of the various columns. We are %%\n"
1333 "%% defining them here because then they are easier to change. %%\n"
1334 "%% Depending on the cell formats we may use them more than once. %%\n"
1336 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
1340 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
1341 ColRowInfo
const * ci
;
1342 char const *colname
= col_name (col
);
1344 ci
= sheet_col_get_info (current_sheet
, col
);
1345 gsf_output_printf (output
, "\\ifthenelse{\\isundefined{\\gnumericCol%s}}"
1346 "{\\newlength{\\gnumericCol%s}}{}\\settowidth{\\gnumericCol%s}"
1347 "{\\begin{tabular}{@{}p{%ipt*\\gnumericScale}@{}}x\\end{tabular}}\n",
1348 colname
, colname
, colname
, ci
->size_pixels
* 10 / 12);
1351 /* Start outputting the table. */
1352 gsf_output_printf (output
, "\n\\begin{longtable}[c]{%%\n");
1353 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
1354 gsf_output_printf (output
, "\tb{\\gnumericCol%s}%%\n", col_name (col
));
1356 gsf_output_printf (output
, "\t}\n\n");
1358 /* Output the table header. */
1359 latex2e_write_table_header (output
, num_cols
);
1362 /* Step through the sheet, writing cells as appropriate. */
1363 for (row
= total_range
.start
.row
; row
<= total_range
.end
.row
; row
++) {
1364 ColRowInfo
const * ri
;
1365 ri
= sheet_row_get_info (current_sheet
, row
);
1366 if (ri
->needs_respan
)
1367 row_calc_spans ((ColRowInfo
*) ri
, row
, current_sheet
);
1369 /* We need to check for horizontal borders at the top of this row */
1371 clines
= g_new0 (GnmStyleBorderType
, length
);
1372 needs_hline
= FALSE
;
1373 this_clines
= clines
;
1374 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
1375 needs_hline
= latex2e_find_hhlines (this_clines
, length
, col
, row
,
1376 current_sheet
, MSTYLE_BORDER_TOP
)
1381 /* or at the bottom of the previous */
1382 if (row
> total_range
.start
.row
) {
1384 this_clines
= clines
;
1385 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
1386 needs_hline
= latex2e_find_hhlines (this_clines
, length
, col
,
1387 row
- 1, current_sheet
,
1388 MSTYLE_BORDER_BOTTOM
)
1394 /* We also need to know vertical borders */
1395 /* We do this here rather than as we output the cells since */
1396 /* we need to know the right connectors! */
1397 prev_vert
= next_vert
;
1398 next_vert
= g_new0 (GnmStyleBorderType
, num_cols
+ 1);
1399 this_vert
= next_vert
;
1400 *this_vert
= latex2e_find_vline (total_range
.start
.col
, row
,
1401 current_sheet
, MSTYLE_BORDER_LEFT
);
1403 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
1404 *this_vert
= latex2e_find_vline (col
, row
, current_sheet
,
1405 MSTYLE_BORDER_RIGHT
);
1410 latex2e_print_hhline (output
, clines
, num_cols
, prev_vert
, next_vert
);
1413 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
1420 cell
= sheet_cell_get (current_sheet
, col
, row
);
1422 /* Check if we are not the first cell in the row.*/
1423 if (col
!= total_range
.start
.col
)
1424 gsf_output_printf (output
, "\t&");
1426 gsf_output_printf (output
, "\t ");
1428 /* Check a merge. */
1429 merge_range
= gnm_sheet_merge_is_corner (current_sheet
, &pos
);
1430 if (merge_range
== NULL
) {
1431 if (gnm_cell_is_empty(cell
))
1432 latex2e_write_blank_multicolumn_cell(output
, col
, row
,
1434 col
- total_range
.start
.col
,
1435 next_vert
, current_sheet
);
1437 latex2e_write_multicolumn_cell(output
, cell
, col
,
1439 col
- total_range
.start
.col
,
1440 next_vert
, current_sheet
);
1444 /* Get the extent of the merge. */
1445 num_merged_cols
= merge_range
->end
.col
- merge_range
->start
.col
+ 1;
1446 num_merged_rows
= merge_range
->end
.row
- merge_range
->start
.row
+ 1;
1448 if (gnm_cell_is_empty(cell
))
1449 latex2e_write_blank_multicolumn_cell(output
, col
, row
,
1452 col
- total_range
.start
.col
,
1453 next_vert
, current_sheet
);
1455 latex2e_write_multicolumn_cell(output
, cell
, col
, num_merged_cols
,
1457 col
- total_range
.start
.col
,
1458 next_vert
, current_sheet
);
1459 col
+= (num_merged_cols
- 1);
1462 gsf_output_printf (output
, "\\\\\n");
1466 /* We need to check for horizontal borders at the bottom of the last row */
1467 clines
= g_new0 (GnmStyleBorderType
, total_range
.end
.col
- total_range
.start
.col
+ 1);
1468 needs_hline
= FALSE
;
1469 /* In case that we are at the very bottom of the sheet we can not */
1470 /* check on the next line! */
1471 if (row
< colrow_max (FALSE
, current_sheet
)) {
1473 this_clines
= clines
;
1474 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
1475 needs_hline
= latex2e_find_hhlines (this_clines
, length
, col
, row
,
1476 current_sheet
, MSTYLE_BORDER_TOP
)
1483 this_clines
= clines
;
1484 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
1485 needs_hline
= latex2e_find_hhlines (this_clines
, length
, col
,
1486 row
- 1, current_sheet
,
1487 MSTYLE_BORDER_BOTTOM
)
1493 latex2e_print_hhline (output
, clines
, num_cols
, next_vert
, NULL
);
1498 gsf_output_puts (output
, "\\end{longtable}\n\n"
1499 "\\ifthenelse{\\isundefined{\\languageshorthands}}"
1500 "{}{\\languageshorthands{\\languagename}}\n"
1501 "\\gnumericTableEnd\n");
1506 * latex2e_table_cell:
1508 * @output: output stream where the cell contents will be written.
1509 * @cell: the cell whose contents are to be written.
1511 * This function creates all the LaTeX code for the cell of a table (i.e. all
1512 * the code that might fall between two ampersands (&)).
1516 latex2e_table_write_cell (GsfOutput
*output
, GnmCell
*cell
)
1518 GnmStyle
const *style
= gnm_cell_get_style (cell
);
1520 if (gnm_style_get_contents_hidden (style
))
1523 if (!gnm_cell_is_empty (cell
)) {
1524 char * rendered_string
;
1526 rendered_string
= gnm_cell_get_rendered_text (cell
);
1527 latex_fputs (rendered_string
, output
);
1528 g_free (rendered_string
);
1534 * latex2e_table_write_file_header:
1536 * @output: Output stream where the cell contents will be written.
1538 * This ouputs the LaTeX header. Kept separate for esthetics.
1542 latex2e_table_write_file_header(GsfOutput
*output
)
1544 gsf_output_puts (output
,
1545 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
1547 "%% This is a LaTeX2e table fragment exported from Gnumeric. %%\n"
1549 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
1554 * latex_table_file_save : The LaTeX2e exporter plugin function.
1556 * @WorkbookView: this provides the way to access the sheet being exported.
1557 * @outpu: where we'll write.
1558 * @all: Whether to write all rows or just the visible ones.
1560 * This writes the top sheet of a Gnumeric workbook as the content of a latex table environment.
1561 * We try to avoid all formatting.
1564 latex_table_file_save_impl (WorkbookView
const *wb_view
, GsfOutput
*output
, gboolean all
)
1567 Sheet
*current_sheet
;
1568 GnmRange total_range
;
1571 /* This is the preamble of the LaTeX2e file. */
1572 latex2e_table_write_file_header(output
);
1574 /* Get the topmost sheet and its range from the plugin function argument. */
1575 current_sheet
= wb_view_cur_sheet(wb_view
);
1576 total_range
= file_saver_sheet_get_extent (current_sheet
);
1578 /* Step through the sheet, writing cells as appropriate. */
1579 for (row
= total_range
.start
.row
; row
<= total_range
.end
.row
; row
++) {
1580 ColRowInfo
const * ri
;
1581 ri
= sheet_row_get_info (current_sheet
, row
);
1582 if (all
|| ri
->visible
) {
1583 if (ri
->needs_respan
)
1584 row_calc_spans ((ColRowInfo
*) ri
, row
, current_sheet
);
1586 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
1588 cell
= sheet_cell_get (current_sheet
, col
, row
);
1590 /* Check if we are not the first cell in the row.*/
1591 if (col
!= total_range
.start
.col
)
1592 gsf_output_printf (output
, "\t&");
1594 if (gnm_cell_is_empty (cell
))
1597 latex2e_table_write_cell(output
, cell
);
1599 gsf_output_printf (output
, "\\\\\n");
1605 * latex_table_file_save : The LaTeX2e exporter plugin function.
1607 * @FileSaver: New structure for file plugins. I don't understand.
1608 * @IOcontext: currently not used but reserved for the future.
1609 * @WorkbookView: this provides the way to access the sheet being exported.
1610 * @output: where we'll write.
1612 * This writes the top sheet of a Gnumeric workbook as the content of a latex table environment.
1613 * We try to avoid all formatting.
1616 latex_table_file_save (G_GNUC_UNUSED GOFileSaver
const *fs
,
1617 G_GNUC_UNUSED GOIOContext
*io_context
,
1618 WorkbookView
const *wb_view
, GsfOutput
*output
)
1620 latex_table_file_save_impl (wb_view
, output
, TRUE
);
1624 * latex_table_visible_file_save : The LaTeX2e exporter plugin function.
1626 * @FileSaver: New structure for file plugins. I don't understand.
1627 * @IOcontext: currently not used but reserved for the future.
1628 * @WorkbookView: this provides the way to access the sheet being exported.
1629 * @output: where we'll write.
1631 * This writes the top sheet of a Gnumeric workbook as the content of a latex table environment.
1632 * We try to avoid all formatting.
1635 latex_table_visible_file_save (G_GNUC_UNUSED GOFileSaver
const *fs
,
1636 G_GNUC_UNUSED GOIOContext
*io_context
,
1637 WorkbookView
const *wb_view
, GsfOutput
*output
)
1639 latex_table_file_save_impl (wb_view
, output
, FALSE
);