/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
groff is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
groff is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
const char *current_roman_font
;
int script_size_reduction
= -1; // negative means reduce by a percentage
int delimiter_factor
= 900;
int delimiter_shortfall
= 50;
int null_delimiter_space
= 12;
// we don't use num3, because we don't have \atop
int axis_height
= 26; // in 100ths of an em
int default_rule_thickness
= 4;
int big_op_spacing1
= 11;
int big_op_spacing2
= 17;
int big_op_spacing3
= 20;
int big_op_spacing4
= 60;
int big_op_spacing5
= 10;
// These are for piles and matrices.
int baseline_sep
= 140; // = num1 + denom1
int shift_down
= 26; // = axis_height
int column_sep
= 100; // = em space
int matrix_side_sep
= 17; // = thin space
int nroff
= 0; // should we grok ndefine or tdefine?
"fat_offset", &fat_offset
,
"accent_width", &accent_width
,
"delimiter_factor", &delimiter_factor
,
"delimiter_shortfall", &delimiter_shortfall
,
"null_delimiter_space", &null_delimiter_space
,
"script_space", &script_space
,
"thin_space", &thin_space
,
"medium_space", &medium_space
,
"thick_space", &thick_space
,
"axis_height", &axis_height
,
"default_rule_thickness", &default_rule_thickness
,
"big_op_spacing1", &big_op_spacing1
,
"big_op_spacing2", &big_op_spacing2
,
"big_op_spacing3", &big_op_spacing3
,
"big_op_spacing4", &big_op_spacing4
,
"big_op_spacing5", &big_op_spacing5
,
"minimum_size", &minimum_size
,
"baseline_sep", &baseline_sep
,
"shift_down", &shift_down
,
"column_sep", &column_sep
,
"matrix_side_sep", &matrix_side_sep
,
"draw_lines", &draw_flag
,
"body_height", &body_height
,
"body_depth", &body_depth
,
void set_param(const char *name
, int value
)
for (int i
= 0; param_table
[i
].name
!= 0; i
++)
if (strcmp(param_table
[i
].name
, name
) == 0) {
*param_table
[i
].ptr
= value
;
error("unrecognised parameter `%1'", name
);
int script_style(int style
)
return style
> SCRIPT_STYLE
? style
- 2 : style
;
int cramped_style(int style
)
return (style
& 1) ? style
- 1 : style
;
// Return 0 if the specified size is bad.
// The caller is responsible for giving the error message.
int set_gsize(const char *s
)
const char *p
= (*s
== '+' || *s
== '-') ? s
+ 1 : s
;
long n
= strtol(p
, &end
, 10);
if (n
<= 0 || *end
!= '\0' || n
> INT_MAX
)
void set_script_reduction(int n
)
script_size_reduction
= n
;
return gfont
? gfont
: "I";
return grfont
? grfont
: "R";
return gbfont
? gbfont
: "B";
void set_gfont(const char *s
)
void set_grfont(const char *s
)
void set_gbfont(const char *s
)
// this must be precisely 2 characters in length
#define COMPATIBLE_REG "0C"
printf(".nr " COMPATIBLE_REG
" \\n(.C\n");
printf(".ds " LINE_STRING
"\n");
printf("\\*[" LINE_STRING
"]\n");
void restore_compatibility()
printf(".cp \\n(" COMPATIBLE_REG
"\n");
void do_text(const char *s
)
printf(".as " LINE_STRING
" \"%s\n", s
);
void set_minimum_size(int n
)
if (script_size_reduction
>= 0)
printf(".ps \\n[.s]-%d>?%d\n", script_size_reduction
, minimum_size
);
printf(".ps (u;\\n[.s]*7+5/10>?%d)*1z\n", minimum_size
);
box::box() : uid(next_uid
++), spacing_type(ORDINARY_TYPE
)
printf(".nr " SAVED_FONT_REG
" \\n[.f]\n");
printf(".nr " SAVED_PREV_FONT_REG
" \\n[.f]\n");
printf(".ft %s\n", get_gfont());
printf(".nr " SAVED_SIZE_REG
" \\n[.s]z\n");
char buf
[INT_DIGITS
+ 1];
sprintf(buf
, "%d", gsize
);
b
= new size_box(strsave(buf
), b
);
current_roman_font
= get_grfont();
// This catches tabs used within \Z (which aren't allowed).
int r
= b
->compute_metrics(DISPLAY_STYLE
);
printf(".ft \\n[" SAVED_PREV_FONT_REG
"]\n");
printf(".ft \\n[" SAVED_FONT_REG
"]\n");
printf(".nr " MARK_OR_LINEUP_FLAG_REG
" %d\n", r
);
printf(".nr " SAVED_MARK_REG
" \\n[" MARK_REG
"]\n");
printf(".nr " MARK_WIDTH_REG
" 0\\n[" WIDTH_FORMAT
"]\n", b
->uid
);
else if (r
== FOUND_LINEUP
)
printf(".if r" SAVED_MARK_REG
" .as " LINE_STRING
" \\h'\\n["
SAVED_MARK_REG
"]u-\\n[" MARK_REG
"]u'\n");
assert(r
== FOUND_NOTHING
);
// The problem here is that the argument to \f is read in copy mode,
// so we cannot use \E there; so we hide it in a string instead.
// Another problem is that if we use \R directly, then the space will
// prevent it working in a macro argument.
printf(".ds " SAVE_FONT_STRING
" "
"\\R'" SAVED_INLINE_FONT_REG
" \\\\n[.f]'"
"\\R'" SAVED_INLINE_PREV_FONT_REG
" \\\\n[.f]'"
"\\R'" SAVED_INLINE_SIZE_REG
" \\\\n[.s]z'"
"\\R'" SAVED_INLINE_PREV_SIZE_REG
" \\\\n[.s]z'"
".ds " RESTORE_FONT_STRING
" "
"\\f[\\\\n[" SAVED_INLINE_PREV_FONT_REG
"]]"
"\\f[\\\\n[" SAVED_INLINE_FONT_REG
"]]"
"\\s'\\\\n[" SAVED_INLINE_PREV_SIZE_REG
"]u'"
"\\s'\\\\n[" SAVED_INLINE_SIZE_REG
"]u'"
printf(".as " LINE_STRING
" \\&\\E*[" SAVE_FONT_STRING
"]");
printf("\\f[%s]", get_gfont());
printf("\\s'\\En[" SAVED_SIZE_REG
"]u'");
current_roman_font
= get_grfont();
printf("\\E*[" RESTORE_FONT_STRING
"]\n");
printf(".if r" SAVED_MARK_REG
" .as " LINE_STRING
" \\h'\\n["
MARK_WIDTH_REG
"]u-\\n[" SAVED_MARK_REG
"]u-(\\n["
WIDTH_FORMAT
"]u-\\n[" MARK_REG
"]u)'\n",
printf(".ne \\n[" HEIGHT_FORMAT
"]u-%dM>?0+(\\n["
DEPTH_FORMAT
"]u-%dM>?0)\n",
b
->uid
, body_height
, b
->uid
, body_depth
);
// gpic defines this register so as to make geqn not produce `\x's
#define EQN_NO_EXTRA_SPACE_REG "0x"
printf(".if !r" EQN_NO_EXTRA_SPACE_REG
" "
".nr " EQN_NO_EXTRA_SPACE_REG
" 0\n");
if (positive_space
>= 0 || negative_space
>= 0) {
printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG
"] "
".as " LINE_STRING
" \\x'-%dM'\n", positive_space
);
printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG
"] "
".as " LINE_STRING
" \\x'%dM'\n", negative_space
);
positive_space
= negative_space
= -1;
printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG
"] "
".if \\n[" HEIGHT_FORMAT
"]>%dM .as " LINE_STRING
" \\x'-(\\n[" HEIGHT_FORMAT
uid
, body_height
, uid
, body_height
);
printf(".if !\\n[" EQN_NO_EXTRA_SPACE_REG
"] "
".if \\n[" DEPTH_FORMAT
"]>%dM .as " LINE_STRING
uid
, body_depth
, uid
, body_depth
);
int box::compute_metrics(int)
printf(".nr " WIDTH_FORMAT
" 0\n", uid
);
printf(".nr " HEIGHT_FORMAT
" 0\n", uid
);
printf(".nr " DEPTH_FORMAT
" 0\n", uid
);
void box::compute_subscript_kern()
printf(".nr " SUB_KERN_FORMAT
" 0\n", uid
);
printf(".nr " SKEW_FORMAT
" 0\n", uid
);
void box::check_tabs(int)
int box::left_is_italic()
int box::right_is_italic()
void box::handle_char_type(int, int)
box_list::box_list(box
*pp
)
for (int i
= 0; i
< 10; i
++)
void box_list::append(box
*pp
)
memcpy(p
, oldp
, sizeof(box
*)*len
);
for (int i
= 0; i
< len
; i
++)
void box_list::list_check_tabs(int level
)
for (int i
= 0; i
< len
; i
++)
pointer_box::pointer_box(box
*pp
) : p(pp
)
spacing_type
= p
->spacing_type
;
pointer_box::~pointer_box()
int pointer_box::compute_metrics(int style
)
int r
= p
->compute_metrics(style
);
printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
void pointer_box::compute_subscript_kern()
p
->compute_subscript_kern();
printf(".nr " SUB_KERN_FORMAT
" \\n[" SUB_KERN_FORMAT
"]\n", uid
, p
->uid
);
void pointer_box::compute_skew()
printf(".nr " SKEW_FORMAT
" 0\\n[" SKEW_FORMAT
"]\n",
void pointer_box::check_tabs(int level
)
int simple_box::compute_metrics(int)
printf(".nr " WIDTH_FORMAT
" 0\\w" DELIMITER_CHAR
, uid
);
printf(DELIMITER_CHAR
"\n");
printf(".nr " HEIGHT_FORMAT
" 0>?\\n[rst]\n", uid
);
printf(".nr " DEPTH_FORMAT
" 0-\\n[rsb]>?0\n", uid
);
printf(".nr " SUB_KERN_FORMAT
" 0-\\n[ssc]>?0\n", uid
);
printf(".nr " SKEW_FORMAT
" 0\\n[skw]\n", uid
);
void simple_box::compute_subscript_kern()
// do nothing, we already computed it in do_metrics
void simple_box::compute_skew()
// do nothing, we already computed it in do_metrics
int simple_box::is_simple()
quoted_text_box::quoted_text_box(char *s
) : text(s
)
quoted_text_box::~quoted_text_box()
void quoted_text_box::output()
tab_box::tab_box() : disabled(0)
// We treat a tab_box as having width 0 for width computations.
void tab_box::check_tabs(int level
)
error("tabs allowed only at outermost level");
spacing_type
= SUPPRESS_TYPE
;
printf("\\h'%dM'", thick_space
);
half_space_box::half_space_box()
spacing_type
= SUPPRESS_TYPE
;
void half_space_box::output()
printf("\\h'%dM'", thin_space
);
void box_list::list_debug_print(const char *sep
)
for (int i
= 1; i
< len
; i
++) {
fprintf(stderr
, "%s", sep
);
void quoted_text_box::debug_print()
fprintf(stderr
, "\"%s\"", (text
? text
: ""));
void half_space_box::debug_print()
void space_box::debug_print()
void tab_box::debug_print()
fprintf(stderr
, "<tab>");