
/******************************************************************************
* MODULE     : typeset.gen.cc
* DESCRIPTION: typeset the tree being edited
* 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.
******************************************************************************/

#include <Editor/edit_typeset.gen.h>
#include <tm_buffer.gen.h>
#include <hashmap.gen.cc>

#module code_edit_typeset
#import edit_typeset
#import tm_buffer
#import code_hashmap (path, hashmap<string,tree>)

box empty_box (path ip, int x1=0, int y1=0, int x2=0, int y2=0);

/******************************************************************************
* Contructors, destructors and notification of modifications
******************************************************************************/

edit_typeset_rep::edit_typeset_rep ():
  the_style (TUPLE),
  cur (hashmap<string,tree> (UNINIT)),
  pre (UNINIT), init (UNINIT), fin (UNINIT),
  env (dis, buf->name,
       buf->ref, (buf->prj==NULL? buf->ref: buf->prj->ref),
       buf->aux, (buf->prj==NULL? buf->aux: buf->prj->aux)),
  ttt (new_typesetter (env, et, path())) { }
edit_typeset_rep::~edit_typeset_rep () { delete_typesetter (ttt); }

typesetter edit_typeset_rep::get_typesetter () { return ttt; }
tree edit_typeset_rep::get_style () { return the_style; }
void edit_typeset_rep::set_style (tree t) { the_style= copy (t); }
hashmap<string,tree> edit_typeset_rep::get_init () { return init; }
hashmap<string,tree> edit_typeset_rep::get_fin () { return fin; }
void edit_typeset_rep::set_fin (hashmap<string,tree> H) { fin= H; }

void
edit_typeset_rep::set_init (hashmap<string,tree> H) {
  init= hashmap<string,tree> (UNINIT);
  add_init (H);
}

void
edit_typeset_rep::add_init (hashmap<string,tree> H) {
  init->join (H);
  ::notify_assign (ttt, path(), et);
  notify_change (THE_ENVIRONMENT);
}

/******************************************************************************
* Processing preamble
******************************************************************************/

void
edit_typeset_rep::typeset_style (tree style) {
  // cout << "Process style " << style << "\n";
  if (L(style) != TUPLE)
    fatal_error ("tuple expected as style",
		 "edit_interface_rep::process_style");

  int i, n= N (style);
  for (i=0; i<n; i++) {
    tree   doc;
    string styp=
      get_radical_file_name (env->base_file_name) * ":$TEXMACS_STYLE_PATH";
    string name= as_string (style[i]) * ".ts";
    if ((!load_tree (styp, name, doc, FALSE)) && is_compound (doc)) {
      typeset_style (extract (doc, "style"));
      env->exec (extract (doc, "body"));
    }
  }
}

void
edit_typeset_rep::typeset_preamble () {
  env->write_default_env ();
  typeset_style (the_style);
  env->patch_env (init);
  env->read_env (pre);
}

void
edit_typeset_rep::typeset_prepare () {
  env->write_env (pre);
  env->style_init_env ();
  env->update ();
}

/******************************************************************************
* Routines for getting information
******************************************************************************/

void
edit_typeset_rep::typeset_invalidate_env () {
  cur= hashmap<path,hashmap<string,tree>> (hashmap<string,tree> (UNINIT));
}

void
edit_typeset_rep::typeset_exec_until (path p) {
  if (N(cur[p])!=0) return;
  if (N(cur)>=25) // avoids out of memory in weird cases
    typeset_invalidate_env ();
  typeset_prepare ();
  exec_until (ttt, p);
  env->read_env (cur (p));
}

bool
edit_typeset_rep::defined_at_cursor (string var) {
  typeset_exec_until (tp);
  return cur[tp]->contains (var);
}

tree
edit_typeset_rep::get_env_value (string var, path p) {
  typeset_exec_until (p);
  tree t= cur[p][var];
  return is_func (t, BACKUP, 2)? t[0]: t;
}

tree
edit_typeset_rep::get_env_value (string var) {
  return get_env_value (var, tp);
}

bool
edit_typeset_rep::defined_at_init (string var) {
  if (init->contains (var)) return TRUE;
  if (N(pre)==0) typeset_preamble ();
  return pre->contains (var);
}

tree
edit_typeset_rep::get_init_value (string var) {
  if (init->contains (var)) {
    tree t= init [var];
    return is_func (t, BACKUP, 2)? t[0]: t;
  }
  if (N(pre)==0) typeset_preamble ();
  tree t= pre [var];
  return is_func (t, BACKUP, 2)? t[0]: t;
}

string
edit_typeset_rep::get_env_string (string var) {
  return as_string (get_env_value (var));
}

string
edit_typeset_rep::get_init_string (string var) {
  return as_string (get_init_value (var));
}

int
edit_typeset_rep::get_env_int (string var) {
  return as_int (get_env_value (var));
}

int
edit_typeset_rep::get_init_int (string var) {
  return as_int (get_init_value (var));
}

double
edit_typeset_rep::get_env_double (string var) {
  return as_double (get_env_value (var));
}

double
edit_typeset_rep::get_init_double (string var) {
  return as_double (get_init_value (var));
}

language
edit_typeset_rep::get_env_language () {
  string mode= get_env_string (MODE);
  if (mode == "text")
    return text_language (get_env_string (TEXT_LANGUAGE));
  else if (mode == "math")
    return math_language (get_env_string (MATH_LANGUAGE));
  else return prog_language (get_env_string (PROG_LANGUAGE));
}

/******************************************************************************
* Initialization
******************************************************************************/

void
edit_typeset_rep::init_style (string name) {
  if ((name == "none") || (name == "") || (name == "style")) the_style= TUPLE;
  else the_style= tree (TUPLE, name);
  ::notify_assign (ttt, path(), et);
  notify_change (THE_ENVIRONMENT);
  buf->need_save= buf->need_autosave= TRUE;
}

void
edit_typeset_rep::init_extra_style (string name) {
  the_style << tree (name);
  ::notify_assign (ttt, path(), et);
  notify_change (THE_ENVIRONMENT);
  buf->need_save= buf->need_autosave= TRUE;
}

void
edit_typeset_rep::init_env (string var, tree by) {
  if (init (var) == by) return;
  init (var)= by;
  ::notify_assign (ttt, path(), et);
  notify_change (THE_ENVIRONMENT);
}

void
edit_typeset_rep::init_default (string var) {
  if (!init->contains (var)) return;
  init->reset (var);
  ::notify_assign (ttt, path(), et);
  notify_change (THE_ENVIRONMENT);
}

/******************************************************************************
* Actual typesetting
******************************************************************************/

void
edit_typeset_rep::typeset (SI& x1, SI& y1, SI& x2, SI& y2) {
  typeset_prepare ();
  eb= empty_box (path ());
  // saves memory, also necessary for change_log update
  eb= ::typeset (ttt, x1, y1, x2, y2);
}

void
edit_typeset_rep::typeset_invalidate_all () {
  ::notify_assign (ttt, path(), et);
  notify_change (THE_ENVIRONMENT);
  typeset_preamble ();
}

#endmodule // code_edit_typeset
