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>
66 #define SHEET_SELECTION_KEY "sheet-selection"
70 LATEX_SINGLE_BORDER
= 1,
71 LATEX_DOUBLE_BORDER
= 2,
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
, "", ""}
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:",""}, { ":",":"}}}}
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?
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.
153 latex_raw_str(char const *p
, GsfOutput
*output
, gboolean utf8
)
155 char const *p_begin
, *p_orig
= p
;
157 if(strncasecmp(p
, "\\L{", 3) == 0){
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? */
169 /* put the string beginning from p_begin to p to output */
170 gsf_output_write(output
, p
- p_begin
, p_begin
);
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.
191 latex_fputs_utf (char const *p
, GsfOutput
*output
)
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
);
202 /* These are the other special characters ~ ^ \ (see Lamport, p.15) */
204 gsf_output_printf (output
, "\\%c{ }", *p
);
207 rlt
= latex_raw_str(p
, output
, TRUE
);
209 gsf_output_puts (output
, "$\\backslash$");
213 /* Are these available only in LaTeX through mathmode? */
215 gsf_output_printf (output
, "$%c$", *p
);
219 gsf_output_write (output
,
220 (g_utf8_next_char (p
)) - p
, p
);
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.
238 latex_math_fputs_utf (char const *p
, GsfOutput
*output
)
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
);
248 /* These are the other special characters ~ (see Lamport, p.15) */
250 gsf_output_printf (output
, "\\%c{ }", *p
);
253 rlt
= latex_raw_str(p
, output
, TRUE
);
255 gsf_output_puts (output
, "$\\backslash$");
260 gsf_output_write (output
,
261 (g_utf8_next_char (p
)) - p
, p
);
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.
278 latex_convert_latin_to_utf (char const *text
)
280 char * encoded_text
= NULL
;
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
);
291 gunichar
* ucs_string
= NULL
;
292 gunichar
* this_unichar
;
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
);
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
);
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.
325 latex_fputs_latin (char const *text
, GsfOutput
*output
)
327 char * encoded_text
= NULL
;
331 encoded_text
= latex_convert_latin_to_utf (text
);
333 for (p
= encoded_text
; *p
; 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
);
341 /* These are the other special characters ~ ^ \ (see Lamport, p.15) */
343 gsf_output_printf (output
, "\\%c{ }", *p
);
346 rlt
= latex_raw_str(p
, output
, FALSE
);
348 gsf_output_puts (output
, "$\\backslash$");
352 /* Are these available only in LaTeX through mathmode? */
353 case '>': case '<': case 'µ':
354 gsf_output_printf (output
, "$%c$", *p
);
358 gsf_output_write (output
, 1, p
);
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.
377 latex_math_fputs_latin (char const *text
, GsfOutput
*output
)
379 char * encoded_text
= NULL
;
383 encoded_text
= latex_convert_latin_to_utf (text
);
385 for (p
= encoded_text
; *p
; p
++) {
388 /* These are the classic TeX symbols $ & % # (see Lamport, p.15) */
389 case '$': case '&': case '%': case '#':
390 gsf_output_printf (output
, "\\%c", *p
);
392 /* These are the other special characters ~ (see Lamport, p.15) */
394 gsf_output_printf (output
, "\\%c{ }", *p
);
397 rlt
= latex_raw_str(p
, output
, FALSE
);
399 gsf_output_puts (output
, "$\\backslash$");
405 gsf_output_write (output
, 1, p
);
409 g_free (encoded_text
);
413 latex_fputs (char const *text
, GsfOutput
*output
)
415 if (gnm_conf_get_plugin_latex_use_utf8 ())
416 latex_fputs_utf (text
, output
);
418 latex_fputs_latin (text
, output
);
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
);
427 latex_math_fputs_latin (text
, output
);
431 cb_find_font_encodings (GnmCellIter
const *iter
, gboolean
*fonts
)
433 GnmCell
*cell
= iter
->cell
;
436 gnm_rendered_value_get_text
437 (gnm_cell_fetch_rendered_value (cell
, TRUE
));
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
)
443 rs
= g_utf8_next_char (rs
);
450 * latex2e_write_font_encodings writes
451 * \usepackage[T2A]{fontenc}
452 * in the presence of cyrillic text
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.
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"
491 "%% This is the header of a LaTeX2e file exported from Gnumeric. %%\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"
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"
509 gsf_output_puts (output
,
510 "%% \\usepackage{ucs} %%\n"
511 "%% \\usepackage[utf8x]{inputenc} %%\n"
512 "%% \\usepackage[T2A]{fontenc} % if cyrillic is used %%\n"
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"
530 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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"
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"
545 "%% We must be able to close or not the document at the end. %%\n"
546 " \\def\\gnumericTableEnd{\\end{document}}\n"
549 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
551 "%% This is the PREAMBLE. Change these values to get the right %%\n"
552 "%% paper size and other niceties. %%\n"
554 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
558 gsf_output_puts (output
,
559 " \\documentclass[12pt%\n"
564 gsf_output_puts (output
,
565 " \\documentclass[12pt%\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
);
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"
593 " \\begin{document}\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"
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"
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"
611 "%% End of the else clause for this file being \\input. %%\n"
614 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
616 "%% The rest is the gnumeric table, except for the closing %%\n"
617 "%% statement. Changes below will alter the table\'s appearance. %%\n"
619 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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"
633 "%% The following setting protects this code from babel shorthands. %%\n"
634 " \\ifthenelse{\\isundefined{\\languageshorthands}}{}{\\languageshorthands{english}}"
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"
640 "\\providecommand\\gnumbox{\\makebox[0pt]}\n"
641 "%%\\providecommand\\gnumbox[1][]{\\makebox}\n"
643 "%% to adjust positions in multirow situations %%\n"
644 "\\setlength{\\bigstrutjot}{\\jot}\n"
645 "\\setlength{\\extrarowheight}{\\doublerulesep}\n"
647 "%% The \\setlongtables command keeps column widths the same across %%\n"
648 "%% pages. Simply comment out next line for varying column widths. %%\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.
664 latex2e_write_table_header(GsfOutput
*output
, int num_cols
)
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"
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:
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
) {
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
);
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
);
758 GnmRange
const * range
;
760 if (result
== GNM_STYLE_BORDER_NONE
)
761 return GNM_STYLE_BORDER_NONE
;
765 range
= gnm_sheet_merge_contains_pos (sheet
, &pos
);
768 if ((which_border
== MSTYLE_BORDER_LEFT
&& col
== range
->start
.col
)
769 || (which_border
== MSTYLE_BORDER_RIGHT
&& col
== range
->end
.col
))
772 return GNM_STYLE_BORDER_NONE
;
778 * latex2e_print_vert_border:
780 * @output: Output stream where the cell contents will be written.
781 * @clines: GnmStyleBorderType indicating the type of border
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.
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
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
,
813 GnmStyleBorderType
*borders
, Sheet
*sheet
)
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
;
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
;
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) {
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");
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) {
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
));
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.
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.
922 latex2e_write_multicolumn_cell (GsfOutput
*output
, GnmCell
*cell
, int start_col
,
923 int num_merged_cols
, int num_merged_rows
,
925 GnmStyleBorderType
*borders
, Sheet
*sheet
)
927 char * rendered_string
;
929 gboolean wrap
= FALSE
;
930 GOFormatFamily cell_format_family
;
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
;
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
;
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) {
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");
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) {
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
));
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}");
1023 case GNM_HALIGN_DISTRIBUTED
:
1024 case GNM_HALIGN_CENTER
:
1025 case GNM_HALIGN_CENTER_ACROSS_SELECTION
:
1026 gsf_output_printf (output
, "\\gnumericPB{\\centering}");
1028 case GNM_HALIGN_LEFT
:
1029 gsf_output_printf (output
, "\\gnumericPB{\\raggedright}");
1031 case GNM_HALIGN_JUSTIFY
:
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 */
1043 switch (gnm_style_default_halign (style
, cell
)) {
1044 case GNM_HALIGN_RIGHT
:
1045 gsf_output_printf (output
, "\\gnumbox[r]{");
1047 case GNM_HALIGN_DISTRIBUTED
:
1048 case GNM_HALIGN_CENTER
:
1049 case GNM_HALIGN_CENTER_ACROSS_SELECTION
:
1050 gsf_output_printf (output
, "\\gnumbox{");
1052 case GNM_HALIGN_LEFT
:
1053 gsf_output_printf (output
, "\\gnumbox[l]{");
1055 case GNM_HALIGN_JUSTIFY
:
1056 gsf_output_printf (output
, "\\gnumbox[s]{");
1059 gsf_output_printf (output
, "\\makebox{");
1063 if (!gnm_cell_is_empty (cell
)) {
1064 /* Check the foreground (text) colour. */
1065 GOColor fore
= gnm_cell_get_render_color (cell
);
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.
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
, "$");
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
, "}");
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 */
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
1169 * Determine the border style
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
;
1182 style
= sheet_style_get (sheet
, col
, row
);
1183 border
= gnm_style_get_border (style
, type
);
1184 if (gnm_style_border_is_blank (border
))
1186 clines
[0] = border
->line_type
;
1190 range
= gnm_sheet_merge_contains_pos (sheet
, &pos
);
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
;
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
1215 latex2e_print_hhline (GsfOutput
*output
, GnmStyleBorderType
*clines
, int n
, GnmStyleBorderType
*prev_vert
,
1216 GnmStyleBorderType
*next_vert
)
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
:
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
:
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
]
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
]
1252 [next_vert
? border_styles
[next_vert
[n
]].latex
:
1253 LATEX_NO_BORDER
].p_2
);
1255 gsf_output_printf (output
, "}\n");
1259 file_saver_sheet_get_extent (Sheet
*sheet
)
1262 = g_object_get_data (G_OBJECT (sheet
->workbook
),
1265 Sheet
*start_sheet
, *end_sheet
;
1269 gnm_rangeref_normalize (range
,
1270 eval_pos_init_sheet (&ep
, sheet
),
1271 &start_sheet
, &end_sheet
,
1273 if (start_sheet
== sheet
)
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.
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
);
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
;
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"
1337 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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"
1343 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\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 */
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
)
1388 /* or at the bottom of the previous */
1389 if (row
> total_range
.start
.row
) {
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
)
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
);
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
);
1417 latex2e_print_hhline (output
, clines
, num_cols
, prev_vert
, next_vert
);
1420 for (col
= total_range
.start
.col
; col
<= total_range
.end
.col
; col
++) {
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&");
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
,
1441 col
- total_range
.start
.col
,
1442 next_vert
, current_sheet
);
1444 latex2e_write_multicolumn_cell(output
, cell
, col
,
1446 col
- total_range
.start
.col
,
1447 next_vert
, current_sheet
);
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
,
1459 col
- total_range
.start
.col
,
1460 next_vert
, current_sheet
);
1462 latex2e_write_multicolumn_cell(output
, cell
, col
, num_merged_cols
,
1464 col
- total_range
.start
.col
,
1465 next_vert
, current_sheet
);
1466 col
+= (num_merged_cols
- 1);
1469 gsf_output_printf (output
, "\\\\\n");
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
)) {
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
)
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
)
1500 latex2e_print_hhline (output
, clines
, num_cols
, next_vert
, NULL
);
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 (&)).
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
))
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.
1549 latex2e_table_write_file_header(GsfOutput
*output
)
1551 gsf_output_puts (output
,
1552 "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"
1554 "%% This is a LaTeX2e table fragment exported from Gnumeric. %%\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.
1571 latex_table_file_save_impl (WorkbookView
const *wb_view
, GsfOutput
*output
, gboolean all
)
1573 Workbook
*wb
= wb_view_get_workbook (wb_view
);
1575 Sheet
*current_sheet
;
1576 GnmRange total_range
;
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
++) {
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
))
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.
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.
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
);