📄 table.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. */#include "table.h"#define BAR_HEIGHT ".25m"#define DOUBLE_LINE_SEP "2p"#define HALF_DOUBLE_LINE_SEP "1p"#define LINE_SEP "2p"#define BODY_DEPTH ".25m"const int DEFAULT_COLUMN_SEPARATION = 3;#define DELIMITER_CHAR "\\[tbl]"#define PREFIX "3"#define SEPARATION_FACTOR_REG PREFIX "sep"#define BOTTOM_REG PREFIX "bot"#define RESET_MACRO_NAME PREFIX "init"#define LINESIZE_REG PREFIX "lps"#define TOP_REG PREFIX "top"#define CURRENT_ROW_REG PREFIX "crow"#define LAST_PASSED_ROW_REG PREFIX "passed"#define TRANSPARENT_STRING_NAME PREFIX "trans"#define QUOTE_STRING_NAME PREFIX "quote"#define SECTION_DIVERSION_NAME PREFIX "section"#define SECTION_DIVERSION_FLAG_REG PREFIX "sflag"#define SAVED_VERTICAL_POS_REG PREFIX "vert"#define NEED_BOTTOM_RULE_REG PREFIX "brule"#define KEEP_MACRO_NAME PREFIX "keep"#define RELEASE_MACRO_NAME PREFIX "release"#define SAVED_FONT_REG PREFIX "fnt"#define SAVED_SIZE_REG PREFIX "sz"#define SAVED_FILL_REG PREFIX "fll"#define SAVED_INDENT_REG PREFIX "ind"#define SAVED_CENTER_REG PREFIX "cent"#define TABLE_DIVERSION_NAME PREFIX "table"#define TABLE_DIVERSION_FLAG_REG PREFIX "tflag"#define TABLE_KEEP_MACRO_NAME PREFIX "tkeep"#define TABLE_RELEASE_MACRO_NAME PREFIX "trelease"#define NEEDED_REG PREFIX "needed"#define REPEATED_MARK_MACRO PREFIX "rmk"#define REPEATED_VPT_MACRO PREFIX "rvpt"#define SUPPRESS_BOTTOM_REG PREFIX "supbot"#define SAVED_DN_REG PREFIX "dn"// this must be one character#define COMPATIBLE_REG PREFIX "c"#define BLOCK_WIDTH_PREFIX PREFIX "tbw"#define BLOCK_DIVERSION_PREFIX PREFIX "tbd"#define BLOCK_HEIGHT_PREFIX PREFIX "tbh"#define SPAN_WIDTH_PREFIX PREFIX "w"#define SPAN_LEFT_NUMERIC_WIDTH_PREFIX PREFIX "lnw"#define SPAN_RIGHT_NUMERIC_WIDTH_PREFIX PREFIX "rnw"#define SPAN_ALPHABETIC_WIDTH_PREFIX PREFIX "aw"#define COLUMN_SEPARATION_PREFIX PREFIX "cs"#define ROW_START_PREFIX PREFIX "rs"#define COLUMN_START_PREFIX PREFIX "cl"#define COLUMN_END_PREFIX PREFIX "ce"#define COLUMN_DIVIDE_PREFIX PREFIX "cd"#define ROW_TOP_PREFIX PREFIX "rt"string block_width_reg(int r, int c);string block_diversion_name(int r, int c);string block_height_reg(int r, int c);string span_width_reg(int start_col, int end_col);string span_left_numeric_width_reg(int start_col, int end_col);string span_right_numeric_width_reg(int start_col, int end_col);string span_alphabetic_width_reg(int start_col, int end_col);string column_separation_reg(int col);string row_start_reg(int r);string column_start_reg(int c);string column_end_reg(int c);string column_divide_reg(int c);string row_top_reg(int r);void set_inline_modifier(const entry_modifier *);void restore_inline_modifier(const entry_modifier *m);void set_modifier(const entry_modifier *);int find_decimal_point(const char *s, char decimal_point_char, const char *delim);string an_empty_string;int location_force_filename = 0;void printfs(const char *, const string &arg1 = an_empty_string, const string &arg2 = an_empty_string, const string &arg3 = an_empty_string, const string &arg4 = an_empty_string, const string &arg5 = an_empty_string);void prints(const string &);inline void prints(char c){ putchar(c);}inline void prints(const char *s){ fputs(s, stdout);}void prints(const string &s){ if (!s.empty()) fwrite(s.contents(), 1, s.length(), stdout);}struct horizontal_span { horizontal_span *next; short start_col; short end_col; horizontal_span(int, int, horizontal_span *);};struct single_line_entry;struct double_line_entry;struct simple_entry;class table_entry {friend class table; table_entry *next; int input_lineno; const char *input_filename;protected: short start_row; short start_col; short end_row; short end_col; const entry_modifier *mod;public: void set_location(); table_entry(const entry_modifier *); virtual ~table_entry(); virtual int divert(int ncols, const string *mw, int *sep); virtual void do_width(); virtual void do_depth(); virtual void print() = 0; virtual void position_vertically() = 0; virtual single_line_entry *to_single_line_entry(); virtual double_line_entry *to_double_line_entry(); virtual simple_entry *to_simple_entry(); virtual int line_type(); virtual void note_double_vrule_on_right(int); virtual void note_double_vrule_on_left(int);};class simple_entry : public table_entry {public: simple_entry(const entry_modifier *); void print(); void position_vertically(); simple_entry *to_simple_entry(); virtual void add_tab(); virtual void simple_print(int);};class empty_entry : public simple_entry {public: empty_entry(const entry_modifier *); int line_type();};class text_entry : public simple_entry {protected: char *contents; void print_contents();public: text_entry(char *, const entry_modifier *); ~text_entry();};void text_entry::print_contents(){ set_inline_modifier(mod); prints(contents); restore_inline_modifier(mod);}class repeated_char_entry : public text_entry {public: repeated_char_entry(char *s, const entry_modifier *m); void simple_print(int);};class simple_text_entry : public text_entry {public: simple_text_entry(char *s, const entry_modifier *m); void do_width();};class left_text_entry : public simple_text_entry {public: left_text_entry(char *s, const entry_modifier *m); void simple_print(int); void add_tab();};class right_text_entry : public simple_text_entry {public: right_text_entry(char *s, const entry_modifier *m); void simple_print(int); void add_tab();};class center_text_entry : public simple_text_entry {public: center_text_entry(char *s, const entry_modifier *m); void simple_print(int); void add_tab();};class numeric_text_entry : public text_entry { int dot_pos;public: numeric_text_entry(char *s, const entry_modifier *m, int pos); void do_width(); void simple_print(int);};class alphabetic_text_entry : public text_entry {public: alphabetic_text_entry(char *s, const entry_modifier *m); void do_width(); void simple_print(int); void add_tab();};class line_entry : public simple_entry {protected: char double_vrule_on_right; char double_vrule_on_left;public: line_entry(const entry_modifier *); void note_double_vrule_on_right(int); void note_double_vrule_on_left(int); void simple_print(int) = 0;};class single_line_entry : public line_entry {public: single_line_entry(const entry_modifier *m); void simple_print(int); single_line_entry *to_single_line_entry(); int line_type();};class double_line_entry : public line_entry {public: double_line_entry(const entry_modifier *m); void simple_print(int); double_line_entry *to_double_line_entry(); int line_type();};class short_line_entry : public simple_entry {public: short_line_entry(const entry_modifier *m); void simple_print(int); int line_type();};class short_double_line_entry : public simple_entry {public: short_double_line_entry(const entry_modifier *m); void simple_print(int); int line_type();};class block_entry : public table_entry { char *contents;protected: void do_divert(int alphabetic, int ncols, const string *mw, int *sep);public: block_entry(char *s, const entry_modifier *m); ~block_entry(); int divert(int ncols, const string *mw, int *sep); void do_width(); void do_depth(); void position_vertically(); void print() = 0;};class left_block_entry : public block_entry {public: left_block_entry(char *s, const entry_modifier *m); void print();};class right_block_entry : public block_entry {public: right_block_entry(char *s, const entry_modifier *m); void print();};class center_block_entry : public block_entry {public: center_block_entry(char *s, const entry_modifier *m); void print();};class alphabetic_block_entry : public block_entry {public: alphabetic_block_entry(char *s, const entry_modifier *m); void print(); int divert(int ncols, const string *mw, int *sep);};table_entry::table_entry(const entry_modifier *m): next(0), start_row(-1), end_row(-1), start_col(-1), end_col(-1), mod(m), input_lineno(-1), input_filename(0){}table_entry::~table_entry(){}int table_entry::divert(int, const string *, int *){ return 0;}void table_entry::do_width(){}single_line_entry *table_entry::to_single_line_entry(){ return 0;}double_line_entry *table_entry::to_double_line_entry(){ return 0;}simple_entry *table_entry::to_simple_entry(){ return 0;}void table_entry::do_depth(){}void table_entry::set_location(){ set_troff_location(input_filename, input_lineno);}int table_entry::line_type(){ return -1;}void table_entry::note_double_vrule_on_right(int){}void table_entry::note_double_vrule_on_left(int){}simple_entry::simple_entry(const entry_modifier *m) : table_entry(m){}void simple_entry::add_tab(){ // do nothing}void simple_entry::simple_print(int){ // do nothing}void simple_entry::position_vertically(){ if (start_row != end_row) switch (mod->vertical_alignment) { case entry_modifier::TOP: printfs(".sp |\\n[%1]u\n", row_start_reg(start_row)); break; case entry_modifier::CENTER: // Peform the motion in two stages so that the center is rounded // vertically upwards even if net vertical motion is upwards. printfs(".sp |\\n[%1]u\n", row_start_reg(start_row)); printfs(".sp \\n[" BOTTOM_REG "]u-\\n[%1]u-1v/2u\n", row_start_reg(start_row)); break; case entry_modifier::BOTTOM: printfs(".sp |\\n[%1]u+\\n[" BOTTOM_REG "]u-\\n[%1]u-1v\n", row_start_reg(start_row)); break; default: assert(0); }}void simple_entry::print(){ prints(".ta"); add_tab(); prints('\n'); set_location(); prints("\\&"); simple_print(0); prints('\n');}simple_entry *simple_entry::to_simple_entry(){ return this;}empty_entry::empty_entry(const entry_modifier *m): simple_entry(m){}int empty_entry::line_type(){ return 0;}text_entry::text_entry(char *s, const entry_modifier *m): contents(s), simple_entry(m){}text_entry::~text_entry(){ a_delete contents;}repeated_char_entry::repeated_char_entry(char *s, const entry_modifier *m): text_entry(s, m){}void repeated_char_entry::simple_print(int){ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); set_inline_modifier(mod); printfs("\\l" DELIMITER_CHAR "\\n[%1]u\\&", span_width_reg(start_col, end_col)); prints(contents); prints(DELIMITER_CHAR); restore_inline_modifier(mod);}simple_text_entry::simple_text_entry(char *s, const entry_modifier *m): text_entry(s, m){}void simple_text_entry::do_width(){ set_location(); printfs(".nr %1 \\n[%1]>?\\w" DELIMITER_CHAR, span_width_reg(start_col, end_col)); print_contents(); prints(DELIMITER_CHAR "\n");}left_text_entry::left_text_entry(char *s, const entry_modifier *m): simple_text_entry(s, m){}void left_text_entry::simple_print(int){ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); print_contents();}// The only point of this is to make `\a' ``work'' as in Unix tbl. Grrr.void left_text_entry::add_tab(){ printfs(" \\n[%1]u", column_end_reg(end_col));}right_text_entry::right_text_entry(char *s, const entry_modifier *m): simple_text_entry(s, m){}void right_text_entry::simple_print(int){ printfs("\\h'|\\n[%1]u'", column_start_reg(start_col)); prints("\002\003");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -