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

📄 div.cc

📁 早期freebsd实现
💻 CC
📖 第 1 页 / 共 2 页
字号:
// -*- 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. */// diversions#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"int exit_started = 0;		// the exit process has startedint done_end_macro = 0;		// the end macro (if any) has finishedint seen_last_page_ejector = 0;	// seen the LAST_PAGE_EJECTOR cookiestatic int began_page_in_end_macro = 0;	// a new page was begun during the end macrostatic int last_post_line_extra_space = 0; // needed for \n(.astatic int nl_reg_contents = -1;static int dl_reg_contents = 0;static int dn_reg_contents = 0;static int vertical_position_traps_flag = 1;static vunits truncated_space;static vunits needed_space;diversion::diversion(symbol s) : nm(s), prev(0), vertical_position(V0), marked_place(V0), high_water_mark(V0){}struct vertical_size {  vunits pre_extra, post_extra, pre, post;  vertical_size(vunits vs, int ls);};vertical_size::vertical_size(vunits vs, int ls): pre_extra(V0), post_extra(V0), pre(vs){  if (ls > 1)    post = vs*(ls - 1);  else    post = V0;}void node::set_vertical_size(vertical_size *){}void extra_size_node::set_vertical_size(vertical_size *v){  if (n < V0) {    if (-n > v->pre_extra)      v->pre_extra = -n;  }  else if (n > v->post_extra)    v->post_extra = n;}void vertical_size_node::set_vertical_size(vertical_size *v){  if (n < V0)    v->pre = -n;  else    v->post = n;}top_level_diversion *topdiv;diversion *curdiv;void do_divert(int append){  tok.skip();  symbol nm = get_name();  if (nm.is_null()) {    if (curdiv->prev) {      diversion *temp = curdiv;      curdiv = curdiv->prev;      delete temp;    }    else      warning(WARN_DI, "diversion stack underflow");  }  else {    macro_diversion *md = new macro_diversion(nm, append);    md->prev = curdiv;    curdiv = md;  }  skip_line();}void divert(){  do_divert(0);}void divert_append(){  do_divert(1);}  void diversion::need(vunits n){  vunits d = distance_to_next_trap();  if (d < n) {    space(d, 1);    truncated_space = -d;    needed_space = n;  }}macro_diversion::macro_diversion(symbol s, int append): diversion(s), max_width(H0){#if 0  if (append) {    /* We don't allow recursive appends eg:      .da a      .a      .di            This causes an infinite loop in troff anyway.      This is because the user could do      .as a foo      in the diversion, and this would mess things up royally,      since there would be two things appending to the same      macro_header.      To make it work, we would have to copy the _contents_      of the macro into which we were diverting; this doesn't      strike me as worthwhile.      However,      .di a      .a      .a      .di       will work and will make `a' contain two copies of what it contained       before; in troff, `a' would contain nothing. */    request_or_macro *rm       = (request_or_macro *)request_dictionary.remove(s);    if (!rm || (mac = rm->to_macro()) == 0)      mac = new macro;  }  else    mac = new macro;#endif  // We can now catch the situation described above by comparing  // the length of the charlist in the macro_header with the length  // stored in the macro. When we detect this, we copy the contents.  mac = new macro;  if (append) {    request_or_macro *rm       = (request_or_macro *)request_dictionary.lookup(s);    if (rm) {      macro *m = rm->to_macro();      if (m)	*mac = *m;    }  }}macro_diversion::~macro_diversion(){  request_or_macro *rm = (request_or_macro *)request_dictionary.lookup(nm);  macro *m = rm ? rm->to_macro() : 0;  if (m) {    *m = *mac;    delete mac;  }  else    request_dictionary.define(nm, mac);  mac = 0;  dl_reg_contents = max_width.to_units();  dn_reg_contents = vertical_position.to_units();}vunits macro_diversion::distance_to_next_trap(){  if (!diversion_trap.is_null() && diversion_trap_pos > vertical_position)    return diversion_trap_pos - vertical_position;  else    // Substract vresolution so that vunits::vunits does not overflow.    return vunits(INT_MAX - vresolution);}void macro_diversion::transparent_output(unsigned char c){  mac->append(c);}void macro_diversion::transparent_output(node *n){  mac->append(n);}void macro_diversion::output(node *nd, int retain_size,			     vunits vs, int ls, hunits width){  vertical_size v(vs, ls);  while (nd != 0) {    nd->set_vertical_size(&v);    node *temp = nd;    nd = nd->next;    if (temp->interpret(mac)) {      delete temp;    }    else {#if 1      temp->freeze_space();#endif      mac->append(temp);    }  }  if (!v.post_extra.is_zero())    last_post_line_extra_space = v.post_extra.to_units();  if (!retain_size) {    v.pre = vs;    v.post = (ls > 1) ? vs*(ls - 1) : V0;  }  if (width > max_width)    max_width = width;  vunits x = v.pre + v.pre_extra + v.post + v.post_extra;  if (vertical_position_traps_flag      && !diversion_trap.is_null() && diversion_trap_pos > vertical_position      && diversion_trap_pos <= vertical_position + x) {    vunits trunc = vertical_position + x - diversion_trap_pos;    if (trunc > v.post)      trunc = v.post;    v.post -= trunc;    x -= trunc;    truncated_space = trunc;    spring_trap(diversion_trap);  }  mac->append(new vertical_size_node(-v.pre));  mac->append(new vertical_size_node(v.post));  mac->append('\n');  vertical_position += x;  if (vertical_position - v.post > high_water_mark)    high_water_mark = vertical_position - v.post;}void macro_diversion::space(vunits n, int){  if (vertical_position_traps_flag      && !diversion_trap.is_null() && diversion_trap_pos > vertical_position      && diversion_trap_pos <= vertical_position + n) {    truncated_space = vertical_position + n - diversion_trap_pos;    n = diversion_trap_pos - vertical_position;    spring_trap(diversion_trap);  }  else if (n + vertical_position < V0)    n = -vertical_position;  mac->append(new diverted_space_node(n));  vertical_position += n;}void macro_diversion::copy_file(const char *filename){  mac->append(new diverted_copy_file_node(filename));}top_level_diversion::top_level_diversion(): page_count(0), have_next_page_number(0), page_length(units_per_inch*11),   page_offset(units_per_inch), prev_page_offset(units_per_inch),   ejecting_page(0), page_trap_list(0), before_first_page(1), no_space_mode(0),  page_number(0), last_page_count(-1){}// find the next trap after postrap *top_level_diversion::find_next_trap(vunits *next_trap_pos){  trap *next_trap = 0;  for (trap *pt = page_trap_list; pt != 0; pt = pt->next)    if (!pt->nm.is_null()) {      if (pt->position >= V0) {	if (pt->position > vertical_position 	    && pt->position < page_length	    && (next_trap == 0 || pt->position < *next_trap_pos)) {	      next_trap = pt;	      *next_trap_pos = pt->position;	    }      }      else {	vunits pos = pt->position;	pos += page_length;	if (pos > 0 && pos > vertical_position && (next_trap == 0 || pos < *next_trap_pos)) {	  next_trap = pt;	  *next_trap_pos = pos;	}      }    }  return next_trap;}vunits top_level_diversion::distance_to_next_trap(){  vunits d;  if (!find_next_trap(&d))    return page_length - vertical_position;  else    return d - vertical_position;}void top_level_diversion::output(node *nd, int retain_size,				 vunits vs, int ls, hunits /*width*/){  no_space_mode = 0;  vunits next_trap_pos;  trap *next_trap = find_next_trap(&next_trap_pos);  if (before_first_page && begin_page())     fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");  vertical_size v(vs, ls);  for (node *tem = nd; tem != 0; tem = tem->next)    tem->set_vertical_size(&v);  if (!v.post_extra.is_zero())    last_post_line_extra_space = v.post_extra.to_units();  if (!retain_size) {    v.pre = vs;    v.post = (ls > 1) ? vs*(ls - 1) : V0;  }  vertical_position += v.pre;  vertical_position += v.pre_extra;  the_output->print_line(page_offset, vertical_position, nd,			 v.pre + v.pre_extra, v.post_extra);  vertical_position += v.post_extra;  if (vertical_position > high_water_mark)    high_water_mark = vertical_position;  if (vertical_position_traps_flag && vertical_position >= page_length)    begin_page();  else if (vertical_position_traps_flag	   && next_trap != 0 && vertical_position >= next_trap_pos) {    nl_reg_contents = vertical_position.to_units();    truncated_space = v.post;    spring_trap(next_trap->nm);  }  else if (v.post > V0) {    vertical_position += v.post;    if (vertical_position_traps_flag	&& next_trap != 0 && vertical_position >= next_trap_pos) {      truncated_space = vertical_position - next_trap_pos;      vertical_position = next_trap_pos;      nl_reg_contents = vertical_position.to_units();      spring_trap(next_trap->nm);    }    else if (vertical_position_traps_flag && vertical_position >= page_length)      begin_page();    else      nl_reg_contents = vertical_position.to_units();  }  else    nl_reg_contents = vertical_position.to_units();}void top_level_diversion::transparent_output(unsigned char c){  if (before_first_page && begin_page())    // This can only happen with the transparent() request.    fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");  const char *s = asciify(c);  while (*s)    the_output->transparent_char(*s++);}void top_level_diversion::transparent_output(node * /*n*/){  error("can't transparently output node at top level");}void top_level_diversion::copy_file(const char *filename){  if (before_first_page && begin_page())    fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");  the_output->copy_file(page_offset, vertical_position, filename);}void top_level_diversion::space(vunits n, int forced){  if (no_space_mode) {    if (!forced)      return;    else      no_space_mode = 0;  }  if (before_first_page) {    if (begin_page()) {      // This happens if there's a top of page trap, and the first-page      // transition is caused by `'sp'.      truncated_space = n > V0 ? n : V0;      return;    }  }  vunits next_trap_pos;  trap *next_trap = find_next_trap(&next_trap_pos);  vunits y = vertical_position + n;  if (vertical_position_traps_flag && next_trap != 0 && y >= next_trap_pos) {    vertical_position = next_trap_pos;    nl_reg_contents = vertical_position.to_units();    truncated_space = y - vertical_position;    spring_trap(next_trap->nm);  }  else if (y < V0) {    vertical_position = V0;    nl_reg_contents = vertical_position.to_units();  }  else if (vertical_position_traps_flag && y >= page_length && n >= V0)    begin_page();  else {    vertical_position = y;    nl_reg_contents = vertical_position.to_units();  }}trap::trap(symbol s, vunits n, trap *p)     : nm(s), next(p), position(n){}void top_level_diversion::add_trap(symbol nm, vunits pos){  trap *first_free_slot = 0;  for (trap **p = &page_trap_list; *p; p = &(*p)->next) {    if ((*p)->nm.is_null()) {      if (first_free_slot == 0)	first_free_slot = *p;    }    else if ((*p)->position == pos) {      (*p)->nm = nm;      return;    }  }  if (first_free_slot) {    first_free_slot->nm = nm;    first_free_slot->position = pos;  }  else    *p = new trap(nm, pos, 0);}  void top_level_diversion::remove_trap(symbol nm){  for (trap *p = page_trap_list; p; p = p->next)    if (p->nm == nm) {      p->nm = NULL_SYMBOL;      return;    }}void top_level_diversion::remove_trap_at(vunits pos){  for (trap *p = page_trap_list; p; p = p->next)    if (p->position == pos) {      p->nm = NULL_SYMBOL;      return;    }}      void top_level_diversion::change_trap(symbol nm, vunits pos){  for (trap *p = page_trap_list; p; p = p->next)    if (p->nm == nm) {      p->position = pos;      return;    }}void top_level_diversion::print_traps(){  for (trap *p = page_trap_list; p; p = p->next)    if (p->nm.is_null())      fprintf(stderr, "  empty\n");    else      fprintf(stderr, "%s\t%d\n", p->nm.contents(), p->position.to_units());  fflush(stderr);}void end_diversions(){  while (curdiv != topdiv) {    error("automatically ending diversion `%1' on exit",	    curdiv->nm.contents());    diversion *tem = curdiv;    curdiv = curdiv->prev;    delete tem;  }}NO_RETURN void cleanup_and_exit(int exit_code){  if (the_output) {    the_output->trailer(topdiv->get_page_length());    delete the_output;  }  exit(exit_code);}// returns non-zero if it sprung a top of page trapint top_level_diversion::begin_page(){  if (exit_started) {    if (page_count == last_page_count	? curenv->is_empty()	: (done_end_macro && (seen_last_page_ejector || began_page_in_end_macro)))      cleanup_and_exit(0);    if (!done_end_macro)      began_page_in_end_macro = 1;  }  if (!the_output)    init_output();  ++page_count;  if (have_next_page_number) {    page_number = next_page_number;    have_next_page_number = 0;  }  else if (before_first_page == 1)    page_number = 1;  else    page_number++;  // spring the top of page trap if there is one  vunits next_trap_pos;  vertical_position = -vresolution;  trap *next_trap = find_next_trap(&next_trap_pos);  vertical_position = V0;  high_water_mark = V0;  ejecting_page = 0;  // If before_first_page was 2, then the top of page transition was undone  // using eg .nr nl 0-1.  See nl_reg::set_value.  if (before_first_page != 2)    the_output->begin_page(page_number, page_length);  before_first_page = 0;  nl_reg_contents = vertical_position.to_units();  if (vertical_position_traps_flag && next_trap != 0 && next_trap_pos == V0) {    truncated_space = V0;    spring_trap(next_trap->nm);    return 1;

⌨️ 快捷键说明

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