2 * Formatting to LaTeX documents.
4 * ----------------------------------------------------------------
7 * Copyright (C) 2004 Mojave Group, Caltech
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation,
12 * version 2.1 of the License.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * Additional permission is given to link this library with the
24 * OpenSSL project's "OpenSSL" library, and with the OCaml runtime,
25 * and you may distribute the linked executables. See the file
26 * LICENSE.libmojave for more details.
28 * Author: Jason Hickey
29 * @email{jyh@cs.caltech.edu}
36 * We hack the indentation in the TeX printer.
37 * Format the data into lines, and print the tabstops in
38 * the background color.
40 * The prefix is the white space that is inserted to
41 * get the left margin right.
44 { mutable tex_current_line
: (bool * string) list
;
45 mutable tex_prefix
: string;
46 tex_print_string
: string -> unit;
47 tex_print_newline
: unit -> unit
51 * Have to escape special characters.
53 let tex_escape_string _linebreaks s
=
54 let len = String.length s
in
60 String.sub s i
(j
- i
)
66 collect_escape i j
"\\ "
68 collect_escape i j
"\\_"
70 collect_escape i j
"\\{"
72 collect_escape i j
"\\}"
74 collect_escape i j
"\\|"
76 collect_escape_space i j
"\\lt"
78 collect_escape_space i j
"\\gt"
87 collect_escape_space i j
(Printf.sprintf
"\\char%i" (Char.code c
))
90 and collect_esc i j s'
=
92 String.sub s i
(j
- i
) ^ s'
95 and collect_escape i j s
=
96 collect_esc i j
(s ^
collect (succ j
) (succ j
))
97 and collect_escape_space i j s
=
98 let s'
= collect (succ j
) (succ j
) in
104 ' '
| '
\\'
| '$'
| '_'
| '^'
| '
&'
| '
}'
| '
{'
-> s'
108 collect_esc i j
(s ^
s''
)
115 let tex_print_string buf
s =
116 buf
.tex_current_line
<- (true, s) :: buf
.tex_current_line
118 let tex_print_invis buf
s =
119 buf
.tex_current_line
<- (false, s) :: buf
.tex_current_line
122 * Extract the entire line.
125 let rec collect line
= function
127 collect ((if vis
then (tex_escape_string true h
) else h
) ^ line
) t
131 collect "" buf
.tex_current_line
133 let tex_visible buf
=
134 let rec collect line
= function
136 collect (if vis
then h ^ line
else line
) t
140 collect "" buf
.tex_current_line
143 (false, "\\" ^
s ^
"{")
145 let tex_push_line buf tags
=
146 let line = tex_line buf
in
147 buf
.tex_print_string line;
148 buf
.tex_current_line
<- [];
149 if line <> "" && line.[String.length
line - 1] != '
\n'
then
151 buf
.tex_print_string (String.make
(List.length tags
) '
}'
);
152 buf
.tex_print_string "\\\\\n";
153 buf
.tex_current_line
<- List.map
make_tag tags
160 * Set up all pending tabstops.
162 let tex_tab_line buf
=
163 buf
.tex_prefix ^
tex_visible buf
167 * Compute all pending tabstops,
168 * then push the line and the new tabstop.
170 let tex_tab buf
(col
, _
) tags
=
173 tex_push_line buf tags
;
177 let tabline = tex_tab_line buf
in
178 tex_push_line buf tags
;
180 if col
>= String.length
tabline then
183 String.sub
tabline 0 col
185 let spacer = Printf.sprintf
"\\phantom{%s}" (tex_escape_string false prefix) in
186 buf
.tex_prefix
<- prefix;
187 buf
.tex_current_line
<- buf
.tex_current_line
@ [false, spacer]
190 buf
.tex_current_line
<- (make_tag s) :: buf
.tex_current_line
193 buf
.tex_current_line
<- (false, "}") :: buf
.tex_current_line
198 let make_tex_printer_aux raw
=
199 let { raw_print_string
= output_string
;
200 raw_print_newline
= output_newline
204 output_string
s 0 (String.length
s)
207 { tex_current_line
= [];
209 tex_print_string = print_string;
210 tex_print_newline
= output_newline
214 { print_string = tex_print_string buf;
215 print_invis
= tex_print_invis buf;
216 print_atomic
= tex_print_string buf;
217 print_tab
= tex_tab buf;
218 print_begin_tag
= tex_tag buf;
219 print_end_tag
= tex_etag buf
224 let make_tex_printer raw
=
225 snd
(make_tex_printer_aux raw
)
230 let print_tex_raw rmargin
buf raw
=
231 let tbuf, info = make_tex_printer_aux raw
in
233 raw
.raw_print_string
s 0 (String.length
s)
235 print_string "\\texfalse\\iftex%\n";
236 print_to_printer
buf rmargin
info;
238 print_string "\\fi\\enmptab%\n";
239 raw
.raw_print_flush
()
242 * The channel and buffer versions.
244 let print_tex_channel rmargin
buf out
=
245 print_tex_raw rmargin
buf (raw_channel_printer out
)
247 let print_tex_buffer rmargin
buf out
=
248 print_tex_raw rmargin
buf (raw_buffer_printer out
)
250 let print_tex_string rmargin
buf =
251 let out = Buffer.create
100 in
252 print_tex_buffer rmargin
buf out;
260 * Caml-master: "compile"