📄 table.cc
字号:
as_string(right_separation)); printfs(".nr TW \\n[%1]\n", column_divide_reg(ncolumns)); if (flags & DOUBLEBOX) { printfs(".nr %1 +" DOUBLE_LINE_SEP "\n", column_divide_reg(0)); printfs(".nr %1 -" DOUBLE_LINE_SEP "\n", column_divide_reg(ncolumns)); }}void table::make_columns_equal(){ int first = -1; // index of first equal column for (int i = 0; i < ncolumns; i++) if (equal[i]) { if (first < 0) { printfs(".nr %1 \\n[%1]", span_width_reg(i, i)); first = i; } else printfs(">?\\n[%1]", span_width_reg(i, i)); } if (first >= 0) { prints('\n'); for (i = first + 1; i < ncolumns; i++) if (equal[i]) printfs(".nr %1 \\n[%2]\n", span_width_reg(i, i), span_width_reg(first, first)); }}void table::compute_widths(){ build_span_list(); int i; horizontal_span *p; prints(".nr " SEPARATION_FACTOR_REG " 1n\n"); for (i = 0; i < ncolumns; i++) { init_span_reg(i, i); if (!minimum_width[i].empty()) printfs(".nr %1 %2\n", span_width_reg(i, i), minimum_width[i]); } for (p = span_list; p; p = p->next) init_span_reg(p->start_col, p->end_col); table_entry *q; for (q = entry_list; q; q = q->next) if (!q->mod->zero_width) q->do_width(); for (i = 0; i < ncolumns; i++) compute_span_width(i, i); for (p = span_list; p; p = p->next) compute_span_width(p->start_col, p->end_col); make_columns_equal(); // Note that divide_span keeps equal width columns equal. for (p = span_list; p; p = p->next) divide_span(p->start_col, p->end_col); for (p = span_list; p; p = p->next) sum_columns(p->start_col, p->end_col); int had_spanning_block = 0; int had_equal_block = 0; for (q = entry_list; q; q = q->next) if (q->divert(ncolumns, minimum_width, (flags & EXPAND) ? column_separation : 0)) { if (q->end_col > q->start_col) had_spanning_block = 1; for (i = q->start_col; i <= q->end_col && !had_equal_block; i++) if (equal[i]) had_equal_block = 1; } if (had_equal_block) make_columns_equal(); if (had_spanning_block) for (p = span_list; p; p = p->next) divide_span(p->start_col, p->end_col); compute_separation_factor(); for (p = span_list; p; p = p->next) sum_columns(p->start_col, p->end_col); compute_column_positions();}void table::print_single_hline(int r){ prints(".vs " LINE_SEP ">?\\n[.V]u\n" ".ls 1\n" "\\v'" BODY_DEPTH "'" "\\s[\\n[" LINESIZE_REG "]]"); if (r > nrows - 1) prints("\\D'l |\\n[TW]u 0'"); else { int start_col = 0; for (;;) { while (start_col < ncolumns && entry[r][start_col] != 0 && entry[r][start_col]->start_row != r) start_col++; for (int end_col = start_col; end_col < ncolumns && (entry[r][end_col] == 0 || entry[r][end_col]->start_row == r); end_col++) ; if (end_col <= start_col) break; printfs("\\h'|\\n[%1]u", column_divide_reg(start_col)); if ((r > 0 && vline[r-1][start_col] == 2) || (r < nrows && vline[r][start_col] == 2)) prints("-" HALF_DOUBLE_LINE_SEP); prints("'"); printfs("\\D'l |\\n[%1]u", column_divide_reg(end_col)); if ((r > 0 && vline[r-1][end_col] == 2) || (r < nrows && vline[r][end_col] == 2)) prints("+" HALF_DOUBLE_LINE_SEP); prints(" 0'"); start_col = end_col; } } prints("\\s0\n"); prints(".ls\n" ".vs\n");}void table::print_double_hline(int r){ prints(".vs " LINE_SEP "+" DOUBLE_LINE_SEP ">?\\n[.V]u\n" ".ls 1\n" "\\v'" BODY_DEPTH "'" "\\s[\\n[" LINESIZE_REG "]]"); if (r > nrows - 1) prints("\\v'-" DOUBLE_LINE_SEP "'" "\\D'l |\\n[TW]u 0'" "\\v'" DOUBLE_LINE_SEP "'" "\\h'|0'" "\\D'l |\\n[TW]u 0'"); else { int start_col = 0; for (;;) { while (start_col < ncolumns && entry[r][start_col] != 0 && entry[r][start_col]->start_row != r) start_col++; for (int end_col = start_col; end_col < ncolumns && (entry[r][end_col] == 0 || entry[r][end_col]->start_row == r); end_col++) ; if (end_col <= start_col) break; const char *left_adjust = 0; if ((r > 0 && vline[r-1][start_col] == 2) || (r < nrows && vline[r][start_col] == 2)) left_adjust = "-" HALF_DOUBLE_LINE_SEP; const char *right_adjust = 0; if ((r > 0 && vline[r-1][end_col] == 2) || (r < nrows && vline[r][end_col] == 2)) right_adjust = "+" HALF_DOUBLE_LINE_SEP; printfs("\\v'-" DOUBLE_LINE_SEP "'" "\\h'|\\n[%1]u", column_divide_reg(start_col)); if (left_adjust) prints(left_adjust); prints("'"); printfs("\\D'l |\\n[%1]u", column_divide_reg(end_col)); if (right_adjust) prints(right_adjust); prints(" 0'"); printfs("\\v'" DOUBLE_LINE_SEP "'" "\\h'|\\n[%1]u", column_divide_reg(start_col)); if (left_adjust) prints(left_adjust); prints("'"); printfs("\\D'l |\\n[%1]u", column_divide_reg(end_col)); if (right_adjust) prints(right_adjust); prints(" 0'"); start_col = end_col; } } prints("\\s0\n" ".ls\n" ".vs\n");}void table::compute_vrule_top_adjust(int start_row, int col, string &result){ if (row_is_all_lines[start_row] && start_row < nrows - 1) { if (row_is_all_lines[start_row] == 2) result = LINE_SEP ">?\\n[.V]u" "+" DOUBLE_LINE_SEP; else result = LINE_SEP ">?\\n[.V]u"; start_row++; } else { result = ""; if (start_row == 0) return; for (stuff *p = stuff_list; p && p->row <= start_row; p = p->next) if (p->row == start_row && (p->is_single_line() || p->is_double_line())) return; } int left = 0; if (col > 0) { table_entry *e = entry[start_row-1][col-1]; if (e && e->start_row == e->end_row) { if (e->to_double_line_entry() != 0) left = 2; else if (e->to_single_line_entry() != 0) left = 1; } } int right = 0; if (col < ncolumns) { table_entry *e = entry[start_row-1][col]; if (e && e->start_row == e->end_row) { if (e->to_double_line_entry() != 0) right = 2; else if (e->to_single_line_entry() != 0) right = 1; } } if (row_is_all_lines[start_row-1] == 0) { if (left > 0 || right > 0) { result += "-" BODY_DEPTH "-" BAR_HEIGHT; if ((left == 2 && right != 2) || (right == 2 && left != 2)) result += "-" HALF_DOUBLE_LINE_SEP; else if (left == 2 && right == 2) result += "+" HALF_DOUBLE_LINE_SEP; } } else if (row_is_all_lines[start_row-1] == 2) { if ((left == 2 && right != 2) || (right == 2 && left != 2)) result += "-" DOUBLE_LINE_SEP; else if (left == 1 || right == 1) result += "-" HALF_DOUBLE_LINE_SEP; }}void table::compute_vrule_bot_adjust(int end_row, int col, string &result){ if (row_is_all_lines[end_row] && end_row > 0) { end_row--; result = ""; } else { for (stuff *p = stuff_list; p && p->row < end_row + 1; p = p->next) ; if (p && p->row == end_row + 1 && p->is_double_line()) { result = "-" DOUBLE_LINE_SEP; return; } if ((p != 0 && p->row == end_row + 1) || end_row == nrows - 1) { result = ""; return; } if (row_is_all_lines[end_row+1] == 1) result = LINE_SEP; else if (row_is_all_lines[end_row+1] == 2) result = LINE_SEP "+" DOUBLE_LINE_SEP; else result = ""; } int left = 0; if (col > 0) { table_entry *e = entry[end_row+1][col-1]; if (e && e->start_row == e->end_row) { if (e->to_double_line_entry() != 0) left = 2; else if (e->to_single_line_entry() != 0) left = 1; } } int right = 0; if (col < ncolumns) { table_entry *e = entry[end_row+1][col]; if (e && e->start_row == e->end_row) { if (e->to_double_line_entry() != 0) right = 2; else if (e->to_single_line_entry() != 0) right = 1; } } if (row_is_all_lines[end_row+1] == 0) { if (left > 0 || right > 0) { result = "1v-" BODY_DEPTH "-" BAR_HEIGHT; if ((left == 2 && right != 2) || (right == 2 && left != 2)) result += "+" HALF_DOUBLE_LINE_SEP; else if (left == 2 && right == 2) result += "-" HALF_DOUBLE_LINE_SEP; } } else if (row_is_all_lines[end_row+1] == 2) { if (left == 2 && right == 2) result += "-" DOUBLE_LINE_SEP; else if (left != 2 && right != 2 && (left == 1 || right == 1)) result += "-" HALF_DOUBLE_LINE_SEP; }}void table::add_vertical_rule(int start_row, int end_row, int col, int is_double){ vrule_list = new vertical_rule(start_row, end_row, col, is_double, vrule_list); compute_vrule_top_adjust(start_row, col, vrule_list->top_adjust); compute_vrule_bot_adjust(end_row, col, vrule_list->bot_adjust);}void table::build_vrule_list(){ int col; if (flags & ALLBOX) { for (col = 1; col < ncolumns; col++) { int start_row = 0; for (;;) { while (start_row < nrows && vline_spanned(start_row, col)) start_row++; if (start_row >= nrows) break; int end_row = start_row; while (end_row < nrows && !vline_spanned(end_row, col)) end_row++; end_row--; add_vertical_rule(start_row, end_row, col, 0); start_row = end_row + 1; } } } if (flags & (BOX|ALLBOX|DOUBLEBOX)) { add_vertical_rule(0, nrows - 1, 0, 0); add_vertical_rule(0, nrows - 1, ncolumns, 0); } for (int end_row = 0; end_row < nrows; end_row++) for (col = 0; col < ncolumns+1; col++) if (vline[end_row][col] > 0 && !vline_spanned(end_row, col) && (end_row == nrows - 1 || vline[end_row+1][col] != vline[end_row][col] || vline_spanned(end_row+1, col))) { for (int start_row = end_row - 1; start_row >= 0 && vline[start_row][col] == vline[end_row][col] && !vline_spanned(start_row, col); start_row--) ; start_row++; add_vertical_rule(start_row, end_row, col, vline[end_row][col] > 1); } for (vertical_rule *p = vrule_list; p; p = p->next) if (p->is_double) for (int r = p->start_row; r <= p->end_row; r++) { if (p->col > 0 && entry[r][p->col-1] != 0 && entry[r][p->col-1]->end_col == p->col-1) { int is_corner = r == p->start_row || r == p->end_row; entry[r][p->col-1]->note_double_vrule_on_right(is_corner); } if (p->col < ncolumns && entry[r][p->col] != 0 && entry[r][p->col]->start_col == p->col) { int is_corner = r == p->start_row || r == p->end_row; entry[r][p->col]->note_double_vrule_on_left(is_corner); } }}void table::define_bottom_macro(){ prints(".eo\n" ".de T#\n" ".if !\\n[" SUPPRESS_BOTTOM_REG "] \\{" "." REPEATED_VPT_MACRO " 0\n" ".mk " SAVED_VERTICAL_POS_REG "\n"); if (flags & (BOX|ALLBOX|DOUBLEBOX)) { prints(".if \\n[T.]&\\n[" NEED_BOTTOM_RULE_REG "] \\{"); print_single_hline(0); prints(".\\}\n"); } prints(".ls 1\n"); for (vertical_rule *p = vrule_list; p; p = p->next) p->contribute_to_bottom_macro(this); if (flags & DOUBLEBOX) prints(".if \\n[T.] \\{.vs " DOUBLE_LINE_SEP ">?\\n[.V]u\n" "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]" "\\D'l \\n[TW]u 0'\\s0\n" ".vs\n" ".\\}\n" ".if \\n[" LAST_PASSED_ROW_REG "]>=0 " ".nr " TOP_REG " \\n[#T]-" DOUBLE_LINE_SEP "\n" ".sp -1\n" "\\v'" BODY_DEPTH "'\\s[\\n[" LINESIZE_REG "]]" "\\D'l 0 |\\n[" TOP_REG "]u-1v'\\s0\n" ".sp -1\n" "\\v'" BODY_DEPTH "'\\h'|\\n[TW]u'\\s[\\n[" LINESIZE_REG "]]" "\\D'l 0 |\\n[" TOP_REG "]u-1v'\\s0\n"); prints(".ls\n"); prints(".nr " LAST_PASSED_ROW_REG " \\n[" CURRENT_ROW_REG "]\n" ".sp |\\n[" SAVED_VERTICAL_POS_REG "]u\n" "." REPEATED_VPT_MACRO " 1\n" ".\\}\n" "..\n" ".ec\n");}// is the vertical line before column c in row r horizontally spanned?int table::vline_spanned(int r, int c){ assert(r >= 0 && r < nrows && c >= 0 && c < ncolumns + 1); return (c != 0 && c != ncolumns && entry[r][c] != 0 && entry[r][c]->start_col != c // horizontally spanning lines don't count && entry[r][c]->to_double_line_entry() == 0 && entry[r][c]->to_single_line_entry() == 0);}int table::row_begins_section(int r){ assert(r >= 0 && r < nrows); for (int i = 0; i < ncolumns; i++) if (entry[r][i] && entry[r][i]->start_row != r) return 0; return 1;}int table::row_ends_section(int r){ assert(r >= 0 && r < nrows); for (int i = 0; i < ncolumns; i++) if (entry[r][i] && entry[r][i]->end_row != r) return 0; return 1;}void table::do_row(int r){ if (!(flags & NOKEEP) && row_begins_section(r)) prints("." KEEP_MACRO_NAME "\n"); int had_line = 0; for (stuff *p = stuff_list; p && p->row < r; p = p->next) ; for (stuff *p1 = p; p1 && p1->row == r; p1 = p1->next) if (!p1->printed && (p1->is_single_line() || p1->is_double_line())) { had_line = 1; break; } if (!had_line && !row_is_all_lines[r]) printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r)); had_line = 0; for (; p && p->row == r; p = p->next) if (!p->printed) { p->print(this); if (!had_line && (p->is_single_line() || p->is_double_line())) { printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r)); had_line = 1; } } // Change the row *after* printing the stuff list (which might contain .TH). printfs("\\*[" TRANSPARENT_STRING_NAME "].nr " CURRENT_ROW_REG " %1\n", as_string(r)); if (!had_line && row_is_all_lines[r]) printfs("." REPEATED_MARK_MACRO " %1\n", row_top_reg(r)); // we might have had a .TH, for example, since we last tried if (!(flags & NOKEEP) && row_begins_section(r)) prints("." KEEP_MACRO_NAME "\n"); printfs(".mk %1\n", row_start_reg(r)); prints(".mk " BOTTOM_REG "\n" "." REPEATED_VPT_MACRO " 0\n"); int c; int row_is_blank = 1; int first_start_row = r; for (c = 0; c < ncolumns; c++) { table_entry *e = entry[r][c]; if (e) { if (e->end_row == r) { e->do_depth(); if (e->start_row < first_start_row) first_start_row = e->start_row; row_is_blank = 0; } c = e->end_col; } } if (row_is_blank) prints(".nr " BOTTOM_REG " +1v\n"); if (row_is_all_lines[r]) { prints(".vs " LINE_SEP); if (row_is_all_lines[r] == 2) prints("+" DOUBLE_LINE_SEP); prints(">?\\n[.V]u\n.ls 1\n"); prints("\\&"); prints("\\v'" BODY_DEPTH); if (row_is_all_lines[r] == 2) prints("-" HALF_DOUBLE_LINE_SEP); prints("'"); for (c = 0; c < ncolumns; c++) { table_entry *e = entry[r][c]; if (e) { if (e->end_row == e->start_row) e->to_simple_entry()->simple_print(1); c = e->end_col; } } prints("\n"); prints(".ls\n" ".vs\n"); prints(".nr " BOTTOM_REG " \\n["
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -