📄 table.cc
字号:
e = new numeric_text_entry(s, f, pos); } } else e = new empty_entry(f); break; case FORMAT_ALPHABETIC: if (!str.empty()) { s = str.extract(); if (is_block) e = new alphabetic_block_entry(s, f); else e = new alphabetic_text_entry(s, f); } else e = new empty_entry(f); break; case FORMAT_VSPAN: do_vspan(r, c); break; case FORMAT_HLINE: if (str.length() != 0) error_with_file_and_line(fn, ln, "non-empty data entry for `_' format ignored"); e = new single_line_entry(f); break; case FORMAT_DOUBLE_HLINE: if (str.length() != 0) error_with_file_and_line(fn, ln, "non-empty data entry for `=' format ignored"); e = new double_line_entry(f); break; default: assert(0); } } if (e) { table_entry *preve = entry[r][c]; if (preve) { /* c s ^ l */ error_with_file_and_line(fn, ln, "row %1, column %2 already spanned", r + 1, c + 1); delete e; } else { e->input_lineno = ln; e->input_filename = fn; e->start_row = e->end_row = r; e->start_col = e->end_col = c; for (table_entry **p = &entry_list; *p; p = &(*p)->next) ; *p = e; entry[r][c] = e; } }}// add vertical lines for row rvoid table::add_vlines(int r, const char *v){ allocate(r); for (int i = 0; i < ncolumns+1; i++) vline[r][i] = v[i];}void table::check(){ table_entry *p = entry_list; int i, j; while (p) { for (i = p->start_row; i <= p->end_row; i++) for (j = p->start_col; j <= p->end_col; j++) assert(entry[i][j] == p); p = p->next; }}void table::print(){ location_force_filename = 1; check(); init_output(); determine_row_type(); compute_widths(); if (!(flags & CENTER)) prints(".if \\n[" SAVED_CENTER_REG "] \\{"); prints(".in +(u;\\n[.l]-\\n[.i]-\\n[TW]/2)\n" ".nr " SAVED_INDENT_REG " \\n[.i]\n"); if (!(flags & CENTER)) prints(".\\}\n"); build_vrule_list(); define_bottom_macro(); do_top(); for (int i = 0; i < nrows; i++) do_row(i); do_bottom();}void table::determine_row_type(){ row_is_all_lines = new char[nrows]; for (int i = 0; i < nrows; i++) { int had_single = 0; int had_double = 0; int had_non_line = 0; for (int c = 0; c < ncolumns; c++) { table_entry *e = entry[i][c]; if (e != 0) { if (e->start_row == e->end_row) { int t = e->line_type(); switch (t) { case -1: had_non_line = 1; break; case 0: // empty break; case 1: had_single = 1; break; case 2: had_double = 1; break; default: assert(0); } if (had_non_line) break; } c = e->end_col; } } if (had_non_line) row_is_all_lines[i] = 0; else if (had_double) row_is_all_lines[i] = 2; else if (had_single) row_is_all_lines[i] = 1; else row_is_all_lines[i] = 0; }}void table::init_output(){ prints(".nr " COMPATIBLE_REG " \\n(.C\n" ".cp 0\n"); if (linesize > 0) printfs(".nr " LINESIZE_REG " %1\n", as_string(linesize)); else prints(".nr " LINESIZE_REG " \\n[.s]\n"); if (!(flags & CENTER)) prints(".nr " SAVED_CENTER_REG " \\n[.ce]\n"); prints(".de " RESET_MACRO_NAME "\n" ".ft \\n[.f]\n" ".ps \\n[.s]\n" ".vs \\n[.v]u\n" ".in \\n[.i]u\n" ".ll \\n[.l]u\n" ".ls \\n[.L]\n" ".ad \\n[.j]\n" ".ie \\n[.u] .fi\n" ".el .nf\n" ".ce \\n[.ce]\n" "..\n" ".nr " SAVED_INDENT_REG " \\n[.i]\n" ".nr " SAVED_FONT_REG " \\n[.f]\n" ".nr " SAVED_SIZE_REG " \\n[.s]\n" ".nr " SAVED_FILL_REG " \\n[.u]\n" ".nr T. 0\n" ".nr " CURRENT_ROW_REG " 0-1\n" ".nr " LAST_PASSED_ROW_REG " 0-1\n" ".nr " SECTION_DIVERSION_FLAG_REG " 0\n" ".ds " TRANSPARENT_STRING_NAME "\n" ".ds " QUOTE_STRING_NAME "\n" ".nr " NEED_BOTTOM_RULE_REG " 1\n" ".nr " SUPPRESS_BOTTOM_REG " 0\n" ".eo\n" ".de " REPEATED_MARK_MACRO "\n" ".mk \\$1\n" ".if !'\\n(.z'' \\!." REPEATED_MARK_MACRO " \"\\$1\"\n" "..\n" ".de " REPEATED_VPT_MACRO "\n" ".vpt \\$1\n" ".if !'\\n(.z'' \\!." REPEATED_VPT_MACRO " \"\\$1\"\n" "..\n"); if (!(flags & NOKEEP)) prints(".de " KEEP_MACRO_NAME "\n" ".if '\\n[.z]'' \\{.ds " QUOTE_STRING_NAME " \\\\\n" ".ds " TRANSPARENT_STRING_NAME " \\!\n" ".di " SECTION_DIVERSION_NAME "\n" ".nr " SECTION_DIVERSION_FLAG_REG " 1\n" ".in 0\n" ".\\}\n" "..\n" ".de " RELEASE_MACRO_NAME "\n" ".if \\n[" SECTION_DIVERSION_FLAG_REG "] \\{" ".di\n" ".in \\n[" SAVED_INDENT_REG "]u\n" ".nr " SAVED_DN_REG " \\n[dn]\n" ".ds " QUOTE_STRING_NAME "\n" ".ds " TRANSPARENT_STRING_NAME "\n" ".nr " SECTION_DIVERSION_FLAG_REG " 0\n" ".if \\n[.t]<=\\n[dn] \\{" ".nr T. 1\n" ".T#\n" ".nr " SUPPRESS_BOTTOM_REG " 1\n" ".sp \\n[.t]u\n" ".nr " SUPPRESS_BOTTOM_REG " 0\n" ".mk #T\n" ".\\}\n" ".if \\n[.t]<=\\n[" SAVED_DN_REG "] " /* Since we turn off traps, it won't get into an infinite loop when we try and print it; it will just go off the bottom of the page. */ ".tm warning: page \\n%: table text block will not fit on one page\n" ".nf\n" ".ls 1\n" "." SECTION_DIVERSION_NAME "\n" ".ls\n" ".rm " SECTION_DIVERSION_NAME "\n" ".\\}\n" "..\n" ".nr " TABLE_DIVERSION_FLAG_REG " 0\n" ".de " TABLE_KEEP_MACRO_NAME "\n" ".if '\\n[.z]'' \\{" ".di " TABLE_DIVERSION_NAME "\n" ".nr " TABLE_DIVERSION_FLAG_REG " 1\n" ".\\}\n" "..\n" ".de " TABLE_RELEASE_MACRO_NAME "\n" ".if \\n[" TABLE_DIVERSION_FLAG_REG "] \\{.br\n" ".di\n" ".nr " SAVED_DN_REG " \\n[dn]\n" ".ne \\n[dn]u+\\n[.V]u\n" ".ie \\n[.t]<=\\n[" SAVED_DN_REG "] " ".tm error: page \\n%: table will not fit on one page; use .TS H/.TH with a supporting macro package\n" ".el \\{" ".in 0\n" ".ls 1\n" ".nf\n" "." TABLE_DIVERSION_NAME "\n" ".\\}\n" ".rm " TABLE_DIVERSION_NAME "\n" ".\\}\n" "..\n"); prints(".ec\n" ".ce 0\n" ".nf\n");}string block_width_reg(int r, int c){ static char name[sizeof(BLOCK_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; sprintf(name, BLOCK_WIDTH_PREFIX "%d,%d", r, c); return string(name);}string block_diversion_name(int r, int c){ static char name[sizeof(BLOCK_DIVERSION_PREFIX)+INT_DIGITS+1+INT_DIGITS]; sprintf(name, BLOCK_DIVERSION_PREFIX "%d,%d", r, c); return string(name);}string block_height_reg(int r, int c){ static char name[sizeof(BLOCK_HEIGHT_PREFIX)+INT_DIGITS+1+INT_DIGITS]; sprintf(name, BLOCK_HEIGHT_PREFIX "%d,%d", r, c); return string(name);}string span_width_reg(int start_col, int end_col){ static char name[sizeof(SPAN_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; sprintf(name, SPAN_WIDTH_PREFIX "%d", start_col); if (end_col != start_col) sprintf(strchr(name, '\0'), ",%d", end_col); return string(name);}string span_left_numeric_width_reg(int start_col, int end_col){ static char name[sizeof(SPAN_LEFT_NUMERIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; sprintf(name, SPAN_LEFT_NUMERIC_WIDTH_PREFIX "%d", start_col); if (end_col != start_col) sprintf(strchr(name, '\0'), ",%d", end_col); return string(name);}string span_right_numeric_width_reg(int start_col, int end_col){ static char name[sizeof(SPAN_RIGHT_NUMERIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; sprintf(name, SPAN_RIGHT_NUMERIC_WIDTH_PREFIX "%d", start_col); if (end_col != start_col) sprintf(strchr(name, '\0'), ",%d", end_col); return string(name);}string span_alphabetic_width_reg(int start_col, int end_col){ static char name[sizeof(SPAN_ALPHABETIC_WIDTH_PREFIX)+INT_DIGITS+1+INT_DIGITS]; sprintf(name, SPAN_ALPHABETIC_WIDTH_PREFIX "%d", start_col); if (end_col != start_col) sprintf(strchr(name, '\0'), ",%d", end_col); return string(name);}string column_separation_reg(int col){ static char name[sizeof(COLUMN_SEPARATION_PREFIX)+INT_DIGITS]; sprintf(name, COLUMN_SEPARATION_PREFIX "%d", col); return string(name);}string row_start_reg(int row){ static char name[sizeof(ROW_START_PREFIX)+INT_DIGITS]; sprintf(name, ROW_START_PREFIX "%d", row); return string(name);} string column_start_reg(int col){ static char name[sizeof(COLUMN_START_PREFIX)+INT_DIGITS]; sprintf(name, COLUMN_START_PREFIX "%d", col); return string(name);} string column_end_reg(int col){ static char name[sizeof(COLUMN_END_PREFIX)+INT_DIGITS]; sprintf(name, COLUMN_END_PREFIX "%d", col); return string(name);}string column_divide_reg(int col){ static char name[sizeof(COLUMN_DIVIDE_PREFIX)+INT_DIGITS]; sprintf(name, COLUMN_DIVIDE_PREFIX "%d", col); return string(name);}string row_top_reg(int row){ static char name[sizeof(ROW_TOP_PREFIX)+INT_DIGITS]; sprintf(name, ROW_TOP_PREFIX "%d", row); return string(name);}void init_span_reg(int start_col, int end_col){ printfs(".nr %1 \\n(.H\n.nr %2 0\n.nr %3 0\n.nr %4 0\n", span_width_reg(start_col, end_col), span_alphabetic_width_reg(start_col, end_col), span_left_numeric_width_reg(start_col, end_col), span_right_numeric_width_reg(start_col, end_col));}void compute_span_width(int start_col, int end_col){ printfs(".nr %1 \\n[%1]>?(\\n[%2]+\\n[%3])\n" ".if \\n[%4] .nr %1 \\n[%1]>?(\\n[%4]+2n)\n", span_width_reg(start_col, end_col), span_left_numeric_width_reg(start_col, end_col), span_right_numeric_width_reg(start_col, end_col), span_alphabetic_width_reg(start_col, end_col)); }// Increase the widths of columns so that the width of any spanning entry// is no greater than the sum of the widths of the columns that it spans.// Ensure that the widths of columns remain equal.void table::divide_span(int start_col, int end_col){ assert(end_col > start_col); printfs(".nr " NEEDED_REG " \\n[%1]-(\\n[%2]", span_width_reg(start_col, end_col), span_width_reg(start_col, start_col)); for (int i = start_col + 1; i <= end_col; i++) { // The column separation may shrink with the expand option. if (!(flags & EXPAND)) printfs("+%1n", as_string(column_separation[i - 1])); printfs("+\\n[%1]", span_width_reg(i, i)); } prints(")\n"); printfs(".nr " NEEDED_REG " \\n[" NEEDED_REG "]/%1\n", as_string(end_col - start_col + 1)); prints(".if \\n[" NEEDED_REG "] \\{"); for (i = start_col; i <= end_col; i++) printfs(".nr %1 +\\n[" NEEDED_REG "]\n", span_width_reg(i, i)); int equal_flag = 0; for (i = start_col; i <= end_col && !equal_flag; i++) if (equal[i]) equal_flag = 1; if (equal_flag) { for (i = 0; i < ncolumns; i++) if (i < start_col || i > end_col) printfs(".nr %1 +\\n[" NEEDED_REG "]\n", span_width_reg(i, i)); } prints(".\\}\n");}void table::sum_columns(int start_col, int end_col){ assert(end_col > start_col); printfs(".nr %1 \\n[%2]", span_width_reg(start_col, end_col), span_width_reg(start_col, start_col)); for (int i = start_col + 1; i <= end_col; i++) printfs("+(%1*\\n[" SEPARATION_FACTOR_REG "])+\\n[%2]", as_string(column_separation[i - 1]), span_width_reg(i, i)); prints('\n');}horizontal_span::horizontal_span(int sc, int ec, horizontal_span *p): start_col(sc), end_col(ec), next(p){}void table::build_span_list(){ span_list = 0; table_entry *p = entry_list; while (p) { if (p->end_col != p->start_col) { for (horizontal_span *q = span_list; q; q = q->next) if (q->start_col == p->start_col && q->end_col == p->end_col) break; if (!q) span_list = new horizontal_span(p->start_col, p->end_col, span_list); } p = p->next; } // Now sort span_list primarily by order of end_row, and secondarily // by reverse order of start_row. This ensures that if we divide // spans using the order in span_list, we will get reasonable results. horizontal_span *unsorted = span_list; span_list = 0; while (unsorted) { for (horizontal_span **pp = &span_list; *pp; pp = &(*pp)->next) if (unsorted->end_col < (*pp)->end_col || (unsorted->end_col == (*pp)->end_col && (unsorted->start_col > (*pp)->start_col))) break; horizontal_span *tem = unsorted->next; unsorted->next = *pp; *pp = unsorted; unsorted = tem; }}void table::compute_separation_factor(){ if (flags & (ALLBOX|BOX|DOUBLEBOX)) left_separation = right_separation = 1; else { for (int i = 0; i < nrows; i++) { if (vline[i][0] > 0) left_separation = 1; if (vline[i][ncolumns] > 0) right_separation = 1; } } if (flags & EXPAND) { int total_sep = left_separation + right_separation; for (int i = 0; i < ncolumns - 1; i++) total_sep += column_separation[i]; if (total_sep != 0) { // Don't let the separation factor be negative. prints(".nr " SEPARATION_FACTOR_REG " \\n[.l]-\\n[.i]"); for (i = 0; i < ncolumns; i++) printfs("-\\n[%1]", span_width_reg(i, i)); printfs("/%1>?0\n", as_string(total_sep)); } }}void table::compute_column_positions(){ printfs(".nr %1 0\n", column_divide_reg(0)); printfs(".nr %1 %2*\\n[" SEPARATION_FACTOR_REG "]\n", column_start_reg(0), as_string(left_separation)); for (int i = 1;; i++) { printfs(".nr %1 \\n[%2]+\\n[%3]\n", column_end_reg(i-1), column_start_reg(i-1), span_width_reg(i-1, i-1)); if (i >= ncolumns) break; printfs(".nr %1 \\n[%2]+(%3*\\n[" SEPARATION_FACTOR_REG "])\n", column_start_reg(i), column_end_reg(i-1), as_string(column_separation[i-1])); printfs(".nr %1 \\n[%2]+\\n[%3]/2\n", column_divide_reg(i), column_end_reg(i-1), column_start_reg(i)); } printfs(".nr %1 \\n[%2]+(%3*\\n[" SEPARATION_FACTOR_REG "])\n", column_divide_reg(ncolumns), column_end_reg(i-1),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -