⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 env.cc

📁 早期freebsd实现
💻 CC
📖 第 1 页 / 共 5 页
字号:
// -*- C++ -*-/* 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 underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING.  If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include "troff.h"#include "symbol.h"#include "dictionary.h"#include "hvunits.h"#include "env.h"#include "request.h"#include "node.h"#include "token.h"#include "div.h"#include "reg.h"#include "charinfo.h"#include "searchpath.h"#include "macropath.h"#include <math.h>symbol default_family("T");enum { ADJUST_LEFT = 0, ADJUST_BOTH = 1, ADJUST_CENTER = 3, ADJUST_RIGHT = 5 };enum { HYPHEN_LAST_LINE = 2, HYPHEN_LAST_CHARS = 4, HYPHEN_FIRST_CHARS = 8 };struct env_list {  environment *env;  env_list *next;  env_list(environment *e, env_list *p) : env(e), next(p) {}};env_list *env_stack;const int NENVIRONMENTS = 10;environment *env_table[NENVIRONMENTS];dictionary env_dictionary(10);environment *curenv;static int next_line_number = 0;charinfo *field_delimiter_char;charinfo *padding_indicator_char;int translate_space_to_dummy = 0;class pending_output_line {  node *nd;  int no_fill;  vunits vs;  int ls;  hunits width;#ifdef WIDOW_CONTROL  int last_line;		// Is it the last line of the paragraph?#endif /* WIDOW_CONTROL */public:  pending_output_line *next;  pending_output_line(node *, int, vunits, int, hunits,		      pending_output_line * = 0);  ~pending_output_line();  int output();#ifdef WIDOW_CONTROL  friend void environment::mark_last_line();  friend void environment::output(node *, int, vunits, int, hunits);#endif /* WIDOW_CONTROL */};pending_output_line::pending_output_line(node *n, int nf, vunits v, int l,					 hunits w, pending_output_line *p): nd(n), no_fill(nf), vs(v), ls(l), width(w),#ifdef WIDOW_CONTROL  last_line(0),#endif /* WIDOW_CONTROL */  next(p){}pending_output_line::~pending_output_line(){  delete_node_list(nd);}int pending_output_line::output(){  if (trap_sprung_flag)    return 0;#ifdef WIDOW_CONTROL  if (next && next->last_line && !no_fill) {    curdiv->need(vs*ls + vunits(vresolution));    if (trap_sprung_flag) {      next->last_line = 0;	// Try to avoid infinite loops.      return 0;    }  }#endif  curdiv->output(nd, no_fill, vs, ls, width);  nd = 0;  return 1;}void environment::output(node *nd, int no_fill, vunits vs, int ls,			 hunits width){#ifdef WIDOW_CONTROL  while (pending_lines) {    if (widow_control && !pending_lines->no_fill && !pending_lines->next)      break;    if (!pending_lines->output())      break;    pending_output_line *tem = pending_lines;    pending_lines = pending_lines->next;    delete tem;  }#else /* WIDOW_CONTROL */  output_pending_lines();#endif /* WIDOW_CONTROL */  if (!trap_sprung_flag && !pending_lines#ifdef WIDOW_CONTROL      && (!widow_control || no_fill)#endif /* WIDOW_CONTROL */      )    curdiv->output(nd, no_fill, vs, ls, width);  else {    for (pending_output_line **p = &pending_lines; *p; p = &(*p)->next)      ;    *p = new pending_output_line(nd, no_fill, vs, ls, width);  }}// a line from .tl goes at the head of the queuevoid environment::output_title(node *nd, int no_fill, vunits vs, int ls,			       hunits width){  if (!trap_sprung_flag)    curdiv->output(nd, no_fill, vs, ls, width);  else    pending_lines = new pending_output_line(nd, no_fill, vs, ls, width,					    pending_lines);}void environment::output_pending_lines(){  while (pending_lines && pending_lines->output()) {    pending_output_line *tem = pending_lines;    pending_lines = pending_lines->next;    delete tem;  }}#ifdef WIDOW_CONTROLvoid environment::mark_last_line(){  if (!widow_control || !pending_lines)    return;  for (pending_output_line *p = pending_lines; p->next; p = p->next)    ;  if (!p->no_fill)    p->last_line = 1;}void widow_control_request(){  int n;  if (has_arg() && get_integer(&n))    curenv->widow_control = n != 0;  else    curenv->widow_control = 1;  skip_line();}#endif /* WIDOW_CONTROL *//* font_size functions */size_range *font_size::size_table = 0;int font_size::nranges = 0;extern "C" {static int compare_ranges(const void *p1, const void *p2){  return ((size_range *)p1)->min - ((size_range *)p2)->min;}}void font_size::init_size_table(int *sizes){  nranges = 0;  while (sizes[nranges*2] != 0)    nranges++;  assert(nranges > 0);  size_table = new size_range[nranges];  for (int i = 0; i < nranges; i++) {    size_table[i].min = sizes[i*2];    size_table[i].max = sizes[i*2 + 1];  }  qsort(size_table, nranges, sizeof(size_range), compare_ranges);}font_size::font_size(int sp){  for (int i = 0; i < nranges; i++) {    if (sp < size_table[i].min) {      if (i > 0 && size_table[i].min - sp >= sp - size_table[i - 1].max)	p = size_table[i - 1].max;      else	p = size_table[i].min;      return;    }    if (sp <= size_table[i].max) {      p = sp;      return;    }  }  p = size_table[nranges - 1].max;}int font_size::to_units(){  return scale(p, units_per_inch, sizescale*72);}// we can't do this in a static constructor because various dictionaries// have to get initialized firstvoid init_environments(){  curenv = env_table[0] = new environment("0");}void tab_character(){  curenv->tab_char = get_optional_char();  skip_line();}void leader_character(){  curenv->leader_char = get_optional_char();  skip_line();}void environment::add_char(charinfo *ci){  if (interrupted)    ;  // don't allow fields in dummy environments  else if (ci == field_delimiter_char && !dummy) {    if (current_field)      wrap_up_field();    else      start_field();  }  else if (current_field && ci == padding_indicator_char)    add_padding();  else if (current_tab) {    if (tab_contents == 0)      tab_contents = new line_start_node;    if (ci != hyphen_indicator_char)      tab_contents = tab_contents->add_char(ci, this, &tab_width);    else      tab_contents = tab_contents->add_discretionary_hyphen();  }  else {    if (line == 0)      start_line();    if (ci != hyphen_indicator_char)      line = line->add_char(ci, this, &width_total);    else      line = line->add_discretionary_hyphen();  }}node *environment::make_char_node(charinfo *ci){  return make_node(ci, this);}void environment::add_node(node *n){  assert(n != 0);  if (current_tab || current_field)    n->freeze_space();  if (interrupted) {    delete n;  }  else if (current_tab) {    n->next = tab_contents;    tab_contents = n;    tab_width += n->width();  }  else {    if (line == 0) {      if (discarding && n->discardable()) {	// XXX possibly: input_line_start -= n->width();	delete n;	return;      }      start_line();    }    width_total += n->width();    space_total += n->nspaces();    n->next = line;    line = n;  }}void environment::add_hyphen_indicator(){  if (current_tab || interrupted || current_field      || hyphen_indicator_char != 0)    return;  if (line == 0)    start_line();  line = line->add_discretionary_hyphen();}int environment::get_hyphenation_flags(){  return hyphenation_flags;}int environment::get_hyphen_line_max(){  return hyphen_line_max;}int environment::get_hyphen_line_count(){  return hyphen_line_count;}int environment::get_center_lines(){  return center_lines;}int environment::get_right_justify_lines(){  return right_justify_lines;}void environment::add_italic_correction(){  if (current_tab) {    if (tab_contents)      tab_contents = tab_contents->add_italic_correction(&tab_width);  }  else if (line)    line = line->add_italic_correction(&width_total);}void environment::space_newline(){  assert(!current_tab && !current_field);  if (interrupted)    return;  hunits x = H0;  if (!translate_space_to_dummy) {    x = env_space_width(this);    if (node_list_ends_sentence(line) == 1)      x += env_sentence_space_width(this);  }  if (line != 0 && line->merge_space(x)) {    width_total += x;    return;  }  add_node(new word_space_node(x));  possibly_break_line(spread_flag);  spread_flag = 0;}void environment::space(){  if (interrupted)    return;  if (current_field && padding_indicator_char == 0) {    add_padding();    return;  }  hunits x = translate_space_to_dummy ? H0 : env_space_width(this);  node *p = current_tab ? tab_contents : line;  hunits *tp = current_tab ? &tab_width : &width_total;  if (p && p->nspaces() == 1 && p->width() == x      && node_list_ends_sentence(p->next) == 1) {    hunits xx = translate_space_to_dummy ? H0 : env_sentence_space_width(this);    if (p->merge_space(xx)) {      *tp += xx;      return;    }  }  if (p && p->merge_space(x)) {    *tp += x;    return;  }  add_node(new word_space_node(x));  possibly_break_line(spread_flag);  spread_flag = 0;}void environment::set_font(symbol nm){  if (interrupted)    return;  if (nm == symbol("P")) {    if (family->make_definite(prev_fontno) < 0)      return;    int tem = fontno;    fontno = prev_fontno;    prev_fontno = tem;  }  else {    int n = symbol_fontno(nm);    if (n < 0) {      n = next_available_font_position();      if (!mount_font(n, nm))	return;    }    if (family->make_definite(n) < 0)      return;    prev_fontno = fontno;    fontno = n;  }}void environment::set_font(int n){  if (interrupted)    return;  if (is_good_fontno(n)) {    prev_fontno = fontno;    fontno = n;  }  else    error("bad font number");}void environment::set_family(symbol fam){  if (fam.is_null()) {    if (prev_family->make_definite(fontno) < 0)      return;    font_family *tem = family;    family = prev_family;    prev_family = tem;  }  else {    font_family *f = lookup_family(fam);    if (f->make_definite(fontno) < 0)      return;    prev_family = family;    family = f;  }}void environment::set_size(int n){  if (interrupted)    return;  if (n == 0) {    font_size temp = prev_size;    prev_size = size;    size = temp;    int temp2 = prev_requested_size;    prev_requested_size = requested_size;    requested_size = temp2;  }  else {    prev_size = size;    size = font_size(n);    prev_requested_size = requested_size;    requested_size = n;  }}void environment::set_char_height(int n){  if (interrupted)    return;  if (n == requested_size || n <= 0)    char_height = 0;  else    char_height = n;}void environment::set_char_slant(int n){  if (interrupted)    return;  char_slant = n;}environment::environment(symbol nm): name(nm),  prev_line_length((units_per_inch*13)/2),  line_length((units_per_inch*13)/2),  prev_title_length((units_per_inch*13)/2),  title_length((units_per_inch*13)/2),  prev_size(sizescale*10),  size(sizescale*10),  requested_size(sizescale*10),  prev_requested_size(sizescale*10),  char_height(0),  char_slant(0),  space_size(12),  sentence_space_size(12),  adjust_mode(ADJUST_BOTH),  fill(1),  interrupted(0),  prev_line_interrupted(0),  center_lines(0),  right_justify_lines(0),  prev_vertical_spacing(points_to_units(12)),  vertical_spacing(points_to_units(12)),  prev_line_spacing(1),  line_spacing(1),  prev_indent(0),  indent(0),  have_temporary_indent(0),  temporary_indent(0),  underline_lines(0),  input_trap_count(0),  prev_text_length(0),  width_total(0),  space_total(0),  input_line_start(0),  control_char('.'),  no_break_control_char('\''),  hyphen_indicator_char(0),  spread_flag(0),  line(0),  pending_lines(0),  discarding(0),  tabs(units_per_inch/2, TAB_LEFT),  current_tab(TAB_NONE),  current_field(0),  margin_character_flags(0),  margin_character_node(0),  margin_character_distance(points_to_units(10)),  numbering_nodes(0),  number_text_separation(1),  line_number_multiple(1),  line_number_indent(0),  no_number_count(0),  tab_char(0),  leader_char(charset_table['.']),  hyphenation_flags(1),  dummy(0),  leader_node(0),#ifdef WIDOW_CONTROL  widow_control(0),#endif /* WIDOW_CONTROL */  hyphen_line_count(0),  hyphen_line_max(-1),  hyphenation_space(H0),  hyphenation_margin(H0),  composite(0){  prev_family = family = lookup_family(default_family);  prev_fontno = fontno = 1;  if (!is_good_fontno(1))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -