
/******************************************************************************
* MODULE     : concat_math.gen.cc
* DESCRIPTION: Typesetting mathematical markup
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
*******************************************************************************
* This software falls under the GNU general public license and comes WITHOUT
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
* If you don't have this file, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
******************************************************************************/

#module code_concat_math

/******************************************************************************
* Grouping markup
******************************************************************************/

void
concater_rep::typeset_group (tree t, path ip) {
  box b= typeset_as_concat (env, t[0], descend (ip, 0));
  print (STD_ITEM, move_box (ip, b, 0, 0, TRUE));
}

/******************************************************************************
* Typesetting special mathematical symbols
******************************************************************************/

void
concater_rep::typeset_left (tree t, path ip) {
  if ((N(t) == 1) && is_atomic (t[0])) {
    string s= "<left-" * t[0]->label * ">";
    box b= text_box (ip, 0, s, env->fn, env->col);
    print (LEFT_BRACKET_ITEM, b);
    // temporarary: use parameters from group-open class in texmath.syx
  }
}

void
concater_rep::typeset_middle (tree t, path ip) {
  if ((N(t) == 1) && is_atomic (t[0])) {
    string s= "<mid-" * t[0]->label * ">";
    box b= text_box (ip, 0, s, env->fn, env->col);
    print (MIDDLE_BRACKET_ITEM, b);
    penalty_min (0);
    // temporarary: use parameters from group-separator class in texmath.syx
  }
}

void
concater_rep::typeset_right (tree t, path ip) {
  if ((N(t) == 1) && is_atomic (t[0])) {
    string s= "<right-" * t[0]->label * ">";
    box b= text_box (ip, 0, s, env->fn, env->col);
    print (RIGHT_BRACKET_ITEM, b);
    // bug: allow hyphenation after ) and before *
    // temporarary: use parameters from group-close class in texmath.syx
  }
}

void
concater_rep::typeset_bigop (tree t, path ip) {
  if ((N(t) == 1) && is_atomic (t[0])) {
    space spc= env->fn->spc;
    string l= t[0]->label;
    string s= "<big-" * l * ">";
    bool flag= (!env->math_condensed) && (l != ".");
    box b= big_operator_box (ip, s, env->fn, env->col,
			     env->display_style? 2: 1);
    if (flag) print (space (spc->min>>1, spc->def>>1, spc->max));
    print (STD_ITEM, b);
    penalty_min (HYPH_PANIC);
    if ((l != "int") && (l != "oint")) with_limits ();
    if (flag) print (spc);
    // temporarary: use parameters from operator-big class in texmath.syx
  }
}

void
concater_rep::typeset_lprime (tree t, path ip) {
  if ((N(t) == 1) && is_atomic (t[0])) {
    tree old_il= env->local_begin_script ();
    path sip= descend (ip, 0);
    box b1, b2= typeset_as_concat (env, t[0], sip);
    b2= symbol_box (sip, b2, N(t[0]->label));
    b2= move_box (sip, b2, env->decode_length (string ("-0.05fn")), 0);
    env->local_end_script (old_il);
    print (LEFT_SUP_ITEM, script_box (ip, b1, b2, env->fn));
    penalty_max (HYPH_INVALID);
  }
}

void
concater_rep::typeset_rprime (tree t, path ip) {
  if ((N(t) == 1) && is_atomic (t[0])) {
    tree old_il= env->local_begin_script ();
    path sip= descend (ip, 0);
    box b1, b2= typeset_as_concat (env, t[0], sip);
    b2= symbol_box (sip, b2, N(t[0]->label));
    b2= move_box (sip, b2, env->decode_length (string ("0.05fn")), 0);
    env->local_end_script (old_il);
    penalty_max (HYPH_INVALID);
    if (N(a)>0) a[N(a)-1]->limits= FALSE;
    print (RIGHT_SUP_ITEM, script_box (ip, b1, b2, env->fn));
  }
}

/******************************************************************************
* Typesetting scripts
******************************************************************************/

void
concater_rep::typeset_below (tree t, path ip) {
  box b1= typeset_as_concat (env, t[0], descend (ip, 0));
  tree old_ds= env->local_begin (DISPLAY_STYLE, "false");
  tree old_mc= env->local_begin (MATH_CONDENSED, "true");
  tree old_il= env->local_begin_script ();
  box b2= typeset_as_concat (env, t[1], descend (ip, 1));
  env->local_end_script (old_il);
  env->local_end (MATH_CONDENSED, old_mc);
  env->local_end (DISPLAY_STYLE, old_ds);
  print (STD_ITEM, limit_box (ip, b1, b2, box (), env->fn, FALSE));
}

void
concater_rep::typeset_above (tree t, path ip) {
  box b1= typeset_as_concat (env, t[0], descend (ip, 0));
  tree old_ds= env->local_begin (DISPLAY_STYLE, "false");
  tree old_mc= env->local_begin (MATH_CONDENSED, "true");
  tree old_il= env->local_begin_script ();
  box b2= typeset_as_concat (env, t[1], descend (ip, 1));
  env->local_end_script (old_il);
  env->local_end (MATH_CONDENSED, old_mc);
  env->local_end (DISPLAY_STYLE, old_ds);
  print (STD_ITEM, limit_box (ip, b1, box (), b2, env->fn, FALSE));
}

void
concater_rep::typeset_script (tree t, path ip, bool right) {
  int type= RIGHT_SUP_ITEM;
  box b1, b2;
  tree old_ds= env->local_begin (DISPLAY_STYLE, "false");
  tree old_mc= env->local_begin (MATH_CONDENSED, "true");
  tree old_il= env->local_begin_script ();
  if (is_func (t, SUB (right))) {
    tree old_vp= env->local_begin (VERTICAL_POS, "-1");
    b1= typeset_as_concat (env, t[0], descend (ip, 0));
    type= right? RIGHT_SUB_ITEM: LEFT_SUB_ITEM;
    env->local_end (VERTICAL_POS, old_vp);
  }
  if (is_func (t, SUP (right))) {
    tree old_vp= env->local_begin (VERTICAL_POS, "1");
    b2= typeset_as_concat (env, t[0], descend (ip, 0));
    type= right? RIGHT_SUP_ITEM: LEFT_SUP_ITEM;
    env->local_end (VERTICAL_POS, old_vp);
  }
  env->local_end_script (old_il);
  env->local_end (MATH_CONDENSED, old_mc);
  env->local_end (DISPLAY_STYLE, old_ds);
  if (right) penalty_max (HYPH_INVALID);
  a << line_item (type, script_box (ip, b1, b2, env->fn), HYPH_INVALID);
  // do not use print, because of italic space
  if (!right) penalty_max (HYPH_INVALID);
}

/******************************************************************************
* Standard mathematical operations
******************************************************************************/

void
concater_rep::typeset_frac (tree t, path ip) {
  bool disp= env->display_style;
  tree old;
  if (disp) old= env->local_begin (DISPLAY_STYLE, "false");
  else old= env->local_begin_script ();
  tree old_vp= env->local_begin (VERTICAL_POS, "1");
  box nom= typeset_as_concat (env, t[0], descend (ip, 0));
  env->local_end (VERTICAL_POS, "-1");
  box den= typeset_as_concat (env, t[1], descend (ip, 1));
  env->local_end (VERTICAL_POS, old_vp);
  font sfn= env->fn;
  if (disp) env->local_end (DISPLAY_STYLE, old);
  else env->local_end_script (old);
  print (STD_ITEM, frac_box (ip, nom, den, env->fn, sfn, env->col));
}

void
concater_rep::typeset_sqrt (tree t, path ip) {
  box b= typeset_as_concat (env, t[0], descend (ip, 0));
  box ind;
  if (N(t)==2) {
    bool disp= env->display_style;
    tree old;
    if (disp) old= env->local_begin (DISPLAY_STYLE, "false");
    tree old_il= env->local_begin_script ();
    ind= typeset_as_concat (env, t[1], descend (ip, 1));
    env->local_end_script (old_il);
    if (disp) env->local_end (DISPLAY_STYLE, old);
  }
  SI sep= env->fn->sep;
  box sqrtb= delimiter_box (decorate_left (ip), "<large-sqrt>",
			    env->fn, env->col, b->y1, b->y2+ sep);
  print (STD_ITEM, sqrt_box (ip, b, ind, sqrtb, env->fn, env->col));
}

void
concater_rep::typeset_wide (tree t, path ip, bool above) {
  box b= typeset_as_concat (env, t[0], descend (ip, 0));
  string s= as_string (t[1]);
  if (b->w() >= (env->fn->wquad)) {
    SI w= env->fn->wline;
    box wideb;
    if (s == "^")
      wideb= wide_hat_box   (decorate_middle (ip), b->x1, b->x2, w, env->col);
    if (s == "~")
      wideb= wide_tilda_box (decorate_middle (ip), b->x1, b->x2, w, env->col);
    if (s == "<bar>")
      wideb= wide_bar_box   (decorate_middle (ip), b->x1, b->x2, w, env->col);
    if (s == "<vect>")
      wideb= wide_vect_box  (decorate_middle (ip), b->x1, b->x2, w, env->col);
    if (s == "<check>")
      wideb= wide_check_box (decorate_middle (ip), b->x1, b->x2, w, env->col);
    if (s == "<breve>")
      wideb= wide_breve_box (decorate_middle (ip), b->x1, b->x2, w, env->col);
    if (!nil (wideb)) {
      print (STD_ITEM, wide_box (ip, b, wideb, env->fn, env->fn->sep, above));
      return;
    }
  }
  box wideb= text_box (decorate_middle (ip), 0, s, env->fn, env->col);
  print (STD_ITEM, wide_box (ip, b, wideb, env->fn, -env->fn->yx, above));
}

void
concater_rep::typeset_neg (tree t, path ip) {
  box b= typeset_as_concat (env, t[0], descend (ip, 0));
  print (STD_ITEM, neg_box (ip, b, env->fn, env->col));
}

/******************************************************************************
* Trees and tables
******************************************************************************/

void
concater_rep::typeset_tree (tree t, path ip) {
  int i, n= N(t);
  array<box> bs(n);
  for (i=0; i<n; i++) bs[i]= typeset_as_concat (env, t[i], descend (ip, i));
  print (STD_ITEM, tree_box (ip, bs, env->fn, env->col));
}

void
concater_rep::typeset_table (tree t, path ip) {
  box b= typeset_as_table (env, t, ip);
  print (STD_ITEM, b);
}

#endmodule // code_concat_math
