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

📄 table.cc

📁 早期freebsd实现
💻 CC
📖 第 1 页 / 共 5 页
字号:
text_stuff::text_stuff(const string &s, int r, const char *fn, int ln): contents(s), stuff(r), filename(fn), lineno(ln){}text_stuff::~text_stuff(){}void text_stuff::print(table *){  printed = 1;  prints(".cp \\n(" COMPATIBLE_REG "\n");  set_troff_location(filename, lineno);  prints(contents);  prints(".cp 0\n");  location_force_filename = 1;	// it might have been a .lf command}struct single_hline_stuff : stuff {  single_hline_stuff(int r);  void print(table *);  int is_single_line();};single_hline_stuff::single_hline_stuff(int r) : stuff(r){}void single_hline_stuff::print(table *tbl){  printed = 1;  tbl->print_single_hline(row);}int single_hline_stuff::is_single_line(){  return 1;}struct double_hline_stuff : stuff {  double_hline_stuff(int r);  void print(table *);  int is_double_line();};double_hline_stuff::double_hline_stuff(int r) : stuff(r){}void double_hline_stuff::print(table *tbl){  printed = 1;  tbl->print_double_hline(row);}int double_hline_stuff::is_double_line(){  return 1;}struct vertical_rule {  vertical_rule *next;  short start_row;  short end_row;  short col;  char is_double;  string top_adjust;  string bot_adjust;  vertical_rule(int sr, int er, int c, int dbl, vertical_rule *);  ~vertical_rule();  void contribute_to_bottom_macro(table *);  void print();};vertical_rule::vertical_rule(int sr, int er, int c, int dbl, vertical_rule *p): start_row(sr), end_row(er), col(c), is_double(dbl), next(p){}vertical_rule::~vertical_rule(){}void vertical_rule::contribute_to_bottom_macro(table *tbl){  printfs(".if \\n[" CURRENT_ROW_REG "]>=%1",	  as_string(start_row));  if (end_row != tbl->get_nrows() - 1)    printfs("&(\\n[" CURRENT_ROW_REG "]<%1)",	    as_string(end_row));  prints(" \\{");  printfs(".if %1<=\\n[" LAST_PASSED_ROW_REG "] .nr %2 \\n[#T]\n",	  as_string(start_row),	  row_top_reg(start_row));  const char *offset_table[3];  if (is_double) {    offset_table[0] = "-" HALF_DOUBLE_LINE_SEP;    offset_table[1] = "+" HALF_DOUBLE_LINE_SEP;    offset_table[2] = 0;  }  else {    offset_table[0] = "";    offset_table[1] = 0;  }  for (const char **offsetp = offset_table; *offsetp; offsetp++) {    prints(".sp -1\n"	   "\\v'" BODY_DEPTH);    if (!bot_adjust.empty())      printfs("+%1", bot_adjust);    prints("'");    printfs("\\h'\\n[%1]u%3'\\s[\\n[" LINESIZE_REG "]]\\D'l 0 |\\n[%2]u-1v",	    column_divide_reg(col),	    row_top_reg(start_row),	    *offsetp);    if (!bot_adjust.empty())      printfs("-(%1)", bot_adjust);    // don't perform the top adjustment if the top is actually #T    if (!top_adjust.empty())      printfs("+((%1)*(%2>\\n[" LAST_PASSED_ROW_REG "]))",	      top_adjust,	      as_string(start_row));    prints("'\\s0\n");  }  prints(".\\}\n");}void vertical_rule::print(){  printfs("\\*[" TRANSPARENT_STRING_NAME "]"	  ".if %1<=\\*[" QUOTE_STRING_NAME "]\\n[" LAST_PASSED_ROW_REG "] "	  ".nr %2 \\*[" QUOTE_STRING_NAME "]\\n[#T]\n",	  as_string(start_row),	  row_top_reg(start_row));  const char *offset_table[3];  if (is_double) {    offset_table[0] = "-" HALF_DOUBLE_LINE_SEP;    offset_table[1] = "+" HALF_DOUBLE_LINE_SEP;    offset_table[2] = 0;  }  else {    offset_table[0] = "";    offset_table[1] = 0;  }  for (const char **offsetp = offset_table; *offsetp; offsetp++) {    prints("\\*[" TRANSPARENT_STRING_NAME "].sp -1\n"	   "\\*[" TRANSPARENT_STRING_NAME "]\\v'" BODY_DEPTH);    if (!bot_adjust.empty())      printfs("+%1", bot_adjust);    prints("'");    printfs("\\h'\\n[%1]u%3'"	    "\\s[\\n[" LINESIZE_REG "]]"	    "\\D'l 0 |\\*[" QUOTE_STRING_NAME "]\\n[%2]u-1v",	    column_divide_reg(col),	    row_top_reg(start_row),	    *offsetp);    if (!bot_adjust.empty())      printfs("-(%1)", bot_adjust);    // don't perform the top adjustment if the top is actually #T    if (!top_adjust.empty())      printfs("+((%1)*(%2>\\*[" QUOTE_STRING_NAME "]\\n["	      LAST_PASSED_ROW_REG "]))",	      top_adjust,	      as_string(start_row));    prints("'"	   "\\s0\n");  }}table::table(int nc, unsigned f, int ls, char dpc): ncolumns(nc), flags(f), linesize(ls), decimal_point_char(dpc),  nrows(0), allocated_rows(0), entry(0), entry_list(0),  left_separation(0), right_separation(0), stuff_list(0), vline(0),  vrule_list(0), row_is_all_lines(0), span_list(0){  minimum_width = new string[ncolumns];  column_separation = ncolumns > 1 ? new int[ncolumns - 1] : 0;  equal = new char[ncolumns];  int i;  for (i = 0; i < ncolumns; i++)    equal[i] = 0;  for (i = 0; i < ncolumns-1; i++)    column_separation[i] = DEFAULT_COLUMN_SEPARATION;  delim[0] = delim[1] = '\0';}table::~table(){  for (int i = 0; i < nrows; i++) {    a_delete entry[i];    a_delete vline[i];  }  a_delete entry;  a_delete vline;  while (entry_list) {    table_entry *tem = entry_list;    entry_list = entry_list->next;    delete tem;  }  ad_delete(ncolumns) minimum_width;  a_delete column_separation;  a_delete equal;  while (stuff_list) {    stuff *tem = stuff_list;    stuff_list = stuff_list->next;    delete tem;  }  while (vrule_list) {    vertical_rule *tem = vrule_list;    vrule_list = vrule_list->next;    delete tem;  }  a_delete row_is_all_lines;  while (span_list) {    horizontal_span *tem = span_list;    span_list = span_list->next;    delete tem;  }}void table::set_delim(char c1, char c2){  delim[0] = c1;  delim[1] = c2;}void table::set_minimum_width(int c, const string &w){  assert(c >= 0 && c < ncolumns);  minimum_width[c] = w;}void table::set_column_separation(int c, int n){  assert(c >= 0 && c < ncolumns - 1);  column_separation[c] = n;}void table::set_equal_column(int c){  assert(c >= 0 && c < ncolumns);  equal[c] = 1;}void table::add_stuff(stuff *p){  for (stuff **pp = &stuff_list; *pp; pp = &(*pp)->next)    ;  *pp = p;}void table::add_text_line(int r, const string &s, const char *filename, int lineno){  add_stuff(new text_stuff(s, r, filename, lineno));}void table::add_single_hline(int r){  add_stuff(new single_hline_stuff(r));}void table::add_double_hline(int r){  add_stuff(new double_hline_stuff(r));}void table::allocate(int r){  if (r >= nrows) {    typedef table_entry **PPtable_entry; // work around g++ 1.36.1 bug    if (r >= allocated_rows) {      if (allocated_rows == 0) {	allocated_rows = 16;	if (allocated_rows <= r)	  allocated_rows = r + 1;	entry = new PPtable_entry[allocated_rows];	vline = new char*[allocated_rows];      }      else {	table_entry ***old_entry = entry;	int old_allocated_rows = allocated_rows;	allocated_rows *= 2;	if (allocated_rows <= r)	  allocated_rows = r + 1;	entry = new PPtable_entry[allocated_rows];	memcpy(entry, old_entry, sizeof(table_entry**)*old_allocated_rows);	a_delete old_entry;	char **old_vline = vline;	vline = new char*[allocated_rows];	memcpy(vline, old_vline, sizeof(char*)*old_allocated_rows);	a_delete old_vline;      }    }    assert(allocated_rows > r);    while (nrows <= r) {      entry[nrows] = new table_entry*[ncolumns];      for (int i = 0; i < ncolumns; i++)	entry[nrows][i] = 0;      vline[nrows] = new char[ncolumns+1];      for (i = 0; i < ncolumns+1; i++)	vline[nrows][i] = 0;      nrows++;    }  }}void table::do_hspan(int r, int c){  assert(r >= 0 && c >= 0 && r < nrows && c < ncolumns);  if (c == 0) {    error("first column cannot be horizontally spanned");    return;  }  table_entry *e = entry[r][c];  if (e) {    assert(e->start_row <= r && r <= e->end_row	   && e->start_col <= c && c <= e->end_col	   && e->end_row - e->start_row > 0	   && e->end_col - e->start_col > 0);    return;  }  e = entry[r][c-1];  // e can be 0 if we had an empty entry or an error  if (e == 0)    return;  if (e->start_row != r) {    /*      l l      ^ s */    error("impossible horizontal span at row %1, column %2", r + 1, c + 1);  }  else {    e->end_col = c;    entry[r][c] = e;  }}void table::do_vspan(int r, int c){  assert(r >= 0 && c >= 0 && r < nrows && c < ncolumns);  if (r == 0) {    error("first row cannot be vertically spanned");    return;  }  table_entry *e = entry[r][c];  if (e) {    assert(e->start_row <= r && r <= e->end_row	   && e->start_col <= c && c <= e->end_col	   && e->end_row - e->start_row > 0	   && e->end_col - e->start_col > 0);    return;  }  e = entry[r-1][c];  // e can be 0 if we had an empty entry or an error  if (e == 0)    return;  if (e->start_col != c) {    /* l s       l ^ */    error("impossible vertical span at row %1, column %2", r + 1, c + 1);  }  else {    for (int i = c; i <= e->end_col; i++) {      assert(entry[r][i] == 0);      entry[r][i] = e;    }    e->end_row = r;  }}int find_decimal_point(const char *s, char decimal_point_char,		       const char *delim){  if (s == 0 || *s == '\0')    return -1;  const char *p;  int in_delim = 0;		// is p within eqn delimiters?  // tbl recognises \& even within eqn delimiters; I don't  for (p = s; *p; p++)    if (in_delim) {      if (*p == delim[1])	in_delim = 0;    }    else if (*p == delim[0])      in_delim = 1;    else if (p[0] == '\\' && p[1] == '&')      return p - s;  int possible_pos = -1;  in_delim = 0;  for (p = s; *p; p++)    if (in_delim) {      if (*p == delim[1])	in_delim = 0;    }    else if (*p == delim[0])      in_delim = 1;    else if (p[0] == decimal_point_char && csdigit(p[1]))      possible_pos = p - s;  if (possible_pos >= 0)    return possible_pos;  in_delim = 0;  for (p = s; *p; p++)    if (in_delim) {      if (*p == delim[1])	in_delim = 0;    }    else if (*p == delim[0])      in_delim = 1;    else if (csdigit(*p))      possible_pos = p + 1 - s;  return possible_pos;}void table::add_entry(int r, int c, const string &str, const entry_format *f,		      const char *fn, int ln){  allocate(r);  table_entry *e = 0;  if (str == "\\_") {    e = new short_line_entry(f);  }  else if (str == "\\=") {    e = new short_double_line_entry(f);  }  else if (str == "_") {    single_line_entry *lefte;    if (c > 0 && entry[r][c-1] != 0 &&	(lefte = entry[r][c-1]->to_single_line_entry()) != 0	&& lefte->start_row == r	&& lefte->mod->stagger == f->stagger) {      lefte->end_col = c;      entry[r][c] = lefte;    }    else      e = new single_line_entry(f);  }  else if (str == "=") {    double_line_entry *lefte;    if (c > 0 && entry[r][c-1] != 0 &&	(lefte = entry[r][c-1]->to_double_line_entry()) != 0	&& lefte->start_row == r	&& lefte->mod->stagger == f->stagger) {      lefte->end_col = c;      entry[r][c] = lefte;    }    else      e = new double_line_entry(f);  }  else if (str == "\\^") {    do_vspan(r, c);  }  else if (str.length() > 2 && str[0] == '\\' && str[1] == 'R') {    if (str.search('\n') >= 0)      error_with_file_and_line(fn, ln, "bad repeated character");    else {      char *s = str.substring(2, str.length() - 2).extract();      e = new repeated_char_entry(s, f);    }  }  else {    int is_block = str.search('\n') >= 0;    char *s;    switch (f->type) {    case FORMAT_SPAN:      assert(str.empty());      do_hspan(r, c);      break;    case FORMAT_LEFT:      if (!str.empty()) {	s = str.extract();	if (is_block)	  e = new left_block_entry(s, f);	else	  e = new left_text_entry(s, f);      }      else	e = new empty_entry(f);      break;    case FORMAT_CENTER:      if (!str.empty()) {	s = str.extract();	if (is_block)	  e = new center_block_entry(s, f);	else	  e = new center_text_entry(s, f);      }      else	e = new empty_entry(f);      break;    case FORMAT_RIGHT:      if (!str.empty()) {	s = str.extract();	if (is_block)	  e = new right_block_entry(s, f);	else	  e = new right_text_entry(s, f);      }      else	e = new empty_entry(f);      break;    case FORMAT_NUMERIC:      if (!str.empty()) {	s = str.extract();	if (is_block) {	  error_with_file_and_line(fn, ln, "can't have numeric text block");	  e = new left_block_entry(s, f);	}	else {	  int pos = find_decimal_point(s, decimal_point_char, delim);	  if (pos < 0)	    e = new center_text_entry(s, f);	  else

⌨️ 快捷键说明

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