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

📄 column.cc

📁 早期freebsd实现
💻 CC
字号:
// -*- 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. */#ifdef COLUMN#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 "stringclass.h"void output_file::vjustify(vunits, symbol){  // do nothing}struct justification_spec;struct output_line;class column : public output_file {private:  output_file *out;  vunits bottom;  output_line *col;  output_line **tail;  void add_output_line(output_line *);  void begin_page(int pageno, vunits page_length);  void flush();  void print_line(hunits, vunits, node *, vunits, vunits);  void vjustify(vunits, symbol);  void transparent_char(unsigned char c);  void copy_file(hunits, vunits, const char *);  int is_printing();  void check_bottom();public:  column();  ~column();  void start();  void output();  void justify(const justification_spec &);  void trim();  void reset();  vunits get_bottom();  vunits get_last_extra_space();  int is_active() { return out != 0; }};column *the_column = 0;struct transparent_output_line;struct vjustify_output_line;class output_line {  output_line *next;public:  output_line();  virtual ~output_line();  virtual void output(output_file *, vunits);  virtual transparent_output_line *as_transparent_output_line();  virtual vjustify_output_line *as_vjustify_output_line();  virtual vunits distance();  virtual vunits height();  virtual void reset();  virtual vunits extra_space();	// post line  friend class column;  friend class justification_spec;};class position_output_line : public output_line {  vunits dist;public:  position_output_line(vunits);  vunits distance();};  class node_output_line : public position_output_line {  node *nd;  hunits page_offset;  vunits before;  vunits after;public:  node_output_line(vunits, node *, hunits, vunits, vunits);  ~node_output_line();  void output(output_file *, vunits);  vunits height();  vunits extra_space();};class vjustify_output_line : public position_output_line {  vunits current;  symbol typ;public:  vjustify_output_line(vunits dist, symbol);  vunits height();  vjustify_output_line *as_vjustify_output_line();  void vary(vunits amount);  void reset();  symbol type();};inline symbol vjustify_output_line::type(){  return typ;}class copy_file_output_line : public position_output_line {  symbol filename;  hunits hpos;public:  copy_file_output_line(vunits, const char *, hunits);  void output(output_file *, vunits);};class transparent_output_line : public output_line {  string buf;public:  transparent_output_line();  void output(output_file *, vunits);  void append_char(unsigned char c);  transparent_output_line *as_transparent_output_line();};output_line::output_line() : next(0){}output_line::~output_line(){}void output_line::reset(){}transparent_output_line *output_line::as_transparent_output_line(){  return 0;}vjustify_output_line *output_line::as_vjustify_output_line(){  return 0;}void output_line::output(output_file *, vunits){}vunits output_line::distance(){  return V0;}vunits output_line::height(){  return V0;}vunits output_line::extra_space(){  return V0;}position_output_line::position_output_line(vunits d): dist(d){}vunits position_output_line::distance(){  return dist;}node_output_line::node_output_line(vunits d, node *n, hunits po, vunits b, vunits a): position_output_line(d), nd(n), page_offset(po), before(b), after(a){}node_output_line::~node_output_line(){  delete_node_list(nd);}void node_output_line::output(output_file *out, vunits pos){  out->print_line(page_offset, pos, nd, before, after);  nd = 0;}vunits node_output_line::height(){  return after;}vunits node_output_line::extra_space(){  return after;}vjustify_output_line::vjustify_output_line(vunits d, symbol t): position_output_line(d), typ(t){}void vjustify_output_line::reset(){  current = V0;}vunits vjustify_output_line::height(){  return current;}vjustify_output_line *vjustify_output_line::as_vjustify_output_line(){  return this;}inline void vjustify_output_line::vary(vunits amount){  current += amount;}transparent_output_line::transparent_output_line(){}transparent_output_line *transparent_output_line::as_transparent_output_line(){  return this;}void transparent_output_line::append_char(unsigned char c){  assert(c != 0);  buf += c;}void transparent_output_line::output(output_file *out, vunits){  int len = buf.length();  for (int i = 0; i < len; i++)    out->transparent_char(buf[i]);}copy_file_output_line::copy_file_output_line(vunits d, const char *f, hunits h): position_output_line(d), hpos(h), filename(f){}void copy_file_output_line::output(output_file *out, vunits pos){  out->copy_file(hpos, pos, filename.contents());}column::column(): bottom(V0), col(0), tail(&col), out(0){}column::~column(){  assert(out != 0);  error("automatically outputting column before exiting");  output();  delete the_output;}void column::start(){  assert(out == 0);  if (!the_output)    init_output();  assert(the_output != 0);  out = the_output;  the_output = this;}void column::begin_page(int pageno, vunits page_length){  assert(out != 0);  if (col) {    error("automatically outputting column before beginning next page");    output();    the_output->begin_page(pageno, page_length);  }  else    out->begin_page(pageno, page_length);    }void column::flush(){  assert(out != 0);  out->flush();}int column::is_printing(){  assert(out != 0);  return out->is_printing();}vunits column::get_bottom(){  return bottom;}void column::add_output_line(output_line *ln){  *tail = ln;  bottom += ln->distance();  bottom += ln->height();  ln->next = 0;  tail = &(*tail)->next;}void column::print_line(hunits page_offset, vunits pos, node *nd,			vunits before, vunits after){  assert(out != 0);  add_output_line(new node_output_line(pos - bottom, nd, page_offset, before, after));}void column::vjustify(vunits pos, symbol typ){  assert(out != 0);  add_output_line(new vjustify_output_line(pos - bottom, typ));}void column::transparent_char(unsigned char c){  assert(out != 0);  transparent_output_line *tl = 0;  if (*tail)    tl = (*tail)->as_transparent_output_line();  if (!tl) {    tl = new transparent_output_line;    add_output_line(tl);  }  tl->append_char(c);}void column::copy_file(hunits page_offset, vunits pos, const char *filename){  assert(out != 0);  add_output_line(new copy_file_output_line(pos - bottom, filename, page_offset));}void column::trim(){  output_line **spp = 0;  for (output_line **pp = &col; *pp; pp = &(*pp)->next)    if ((*pp)->as_vjustify_output_line() == 0)      spp = 0;    else if (!spp)      spp = pp;  if (spp) {    output_line *ln = *spp;    *spp = 0;    tail = spp;    while (ln) {      output_line *tem = ln->next;      bottom -= ln->distance();      bottom -= ln->height();      delete ln;      ln = tem;    }  }}void column::reset(){  bottom = V0;  for (output_line *ln = col; ln; ln = ln->next) {    bottom += ln->distance();    ln->reset();    bottom += ln->height();  }}void column::check_bottom(){  vunits b;  for (output_line *ln = col; ln; ln = ln->next) {    b += ln->distance();    b += ln->height();  }  assert(b == bottom);}void column::output(){  assert(out != 0);  vunits vpos(V0);  output_line *ln = col;  while (ln) {    vpos += ln->distance();    ln->output(out, vpos);    vpos += ln->height();    output_line *tem = ln->next;    delete ln;    ln = tem;  }  tail = &col;  bottom = V0;  col = 0;  the_output = out;  out = 0;}vunits column::get_last_extra_space(){  if (!col)    return V0;  for (output_line *p = col; p->next; p = p->next)    ;  return p->extra_space();}class justification_spec {  vunits height;  symbol *type;  vunits *amount;  int n;  int maxn;public:  justification_spec(vunits);  ~justification_spec();  void append(symbol t, vunits v);  void justify(output_line *, vunits *bottomp) const;};justification_spec::justification_spec(vunits h): height(h), n(0), maxn(10){  type = new symbol[maxn];  amount = new vunits[maxn];}justification_spec::~justification_spec(){  a_delete type;  a_delete amount;}void justification_spec::append(symbol t, vunits v){  if (v <= V0) {    if (v < V0)      warning(WARN_RANGE,	      "maximum space for vertical justification must not be negative");    else      warning(WARN_RANGE,	      "maximum space for vertical justification must not be zero");    return;  }  if (n >= maxn) {    maxn *= 2;    symbol *old_type = type;    type = new symbol[maxn];    int i;    for (i = 0; i < n; i++)      type[i] = old_type[i];    a_delete old_type;    vunits *old_amount = amount;    amount = new vunits[maxn];    for (i = 0; i < n; i++)      amount[i] = old_amount[i];    a_delete old_amount;  }  assert(n < maxn);  type[n] = t;  amount[n] = v;  n++;}void justification_spec::justify(output_line *col, vunits *bottomp) const{  if (*bottomp >= height)    return;  vunits total;  output_line *p;  for (p = col; p; p = p->next) {    vjustify_output_line *sp = p->as_vjustify_output_line();    if (sp) {      symbol t = sp->type();      for (int i = 0; i < n; i++) {	if (t == type[i])	  total += amount[i];      }    }  }  vunits gap = height - *bottomp;  for (p = col; p; p = p->next) {    vjustify_output_line *sp = p->as_vjustify_output_line();    if (sp) {      symbol t = sp->type();      for (int i = 0; i < n; i++) {	if (t == type[i]) {	  if (total <= gap) {	    sp->vary(amount[i]);	    gap -= amount[i];	  }	  else {	    // gap < total	    vunits v = scale(amount[i], gap, total);	    sp->vary(v);	    gap -= v;	  }	  total -= amount[i];	}      }    }  }  assert(total == V0);  *bottomp = height - gap;}  void column::justify(const justification_spec &js){  check_bottom();  js.justify(col, &bottom);  check_bottom();}void column_justify(){  vunits height;  if (!the_column->is_active())    error("can't justify column - column not active");  else if (get_vunits(&height, 'v')) {    justification_spec js(height);    symbol nm = get_long_name(1);    if (!nm.is_null()) {      vunits v;      if (get_vunits(&v, 'v')) {	js.append(nm, v);	int err = 0;	while (has_arg()) {	  nm = get_long_name(1);	  if (nm.is_null()) {	    err = 1;	    break;	  }	  if (!get_vunits(&v, 'v')) {	    err = 1;	    break;	  }	  js.append(nm, v);	}	if (!err)	  the_column->justify(js);      }    }  }  skip_line();}void column_start(){  if (the_column->is_active())    error("can't start column - column already active");  else    the_column->start();  skip_line();}void column_output(){  if (!the_column->is_active())    error("can't output column - column not active");  else    the_column->output();  skip_line();}void column_trim(){  if (!the_column->is_active())    error("can't trim column - column not active");  else    the_column->trim();  skip_line();}void column_reset(){  if (!the_column->is_active())    error("can't reset column - column not active");  else    the_column->reset();  skip_line();}class column_bottom_reg : public reg {public:  const char *get_string();};const char *column_bottom_reg::get_string(){  return itoa(the_column->get_bottom().to_units());}class column_extra_space_reg : public reg {public:  const char *get_string();};const char *column_extra_space_reg::get_string(){  return itoa(the_column->get_last_extra_space().to_units());}class column_active_reg : public reg {public:  const char *get_string();};const char *column_active_reg::get_string(){  return the_column->is_active() ? "1" : "0";}static int no_vjustify_mode = 0;class vjustify_node : public node {  symbol typ;public:  vjustify_node(symbol);  int reread(int *);  const char *type();  int same(node *);  node *copy();};vjustify_node::vjustify_node(symbol t): typ(t){}node *vjustify_node::copy(){  return new vjustify_node(typ);}const char *vjustify_node::type(){  return "vjustify_node";}int vjustify_node::same(node *nd){  return typ == ((vjustify_node *)nd)->typ;}int vjustify_node::reread(int *bolp){  curdiv->vjustify(typ);  *bolp = 1;  return 1;}void macro_diversion::vjustify(symbol type){  if (!no_vjustify_mode)    mac->append(new vjustify_node(type));}void top_level_diversion::vjustify(symbol type){  if (no_space_mode || no_vjustify_mode)    return;  assert(first_page_begun);	// I'm not sure about this.  the_output->vjustify(vertical_position, type);}void no_vjustify(){  skip_line();  no_vjustify_mode = 1;}void restore_vjustify(){  skip_line();  no_vjustify_mode = 0;}void init_column_requests(){  the_column = new column;  init_request("cols", column_start);  init_request("colo", column_output);  init_request("colj", column_justify);  init_request("colr", column_reset);  init_request("colt", column_trim);  init_request("nvj", no_vjustify);  init_request("rvj", restore_vjustify);  number_reg_dictionary.define(".colb", new column_bottom_reg);  number_reg_dictionary.define(".colx", new column_extra_space_reg);  number_reg_dictionary.define(".cola", new column_active_reg);  number_reg_dictionary.define(".nvj",			       new constant_int_reg(&no_vjustify_mode));}#endif /* COLUMN */

⌨️ 快捷键说明

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