📄 main.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 MAX_POINT_SIZE 99#define MAX_VERTICAL_SPACING 72static int compatible_flag = 0;class table_input { FILE *fp; enum { START, MIDDLE, REREAD_T, REREAD_TE, REREAD_E, END, ERROR } state; string unget_stack;public: table_input(FILE *); int get(); int ended() { return unget_stack.empty() && state == END; } void unget(char);};table_input::table_input(FILE *p): fp(p), state(START){}void table_input::unget(char c){ assert(c != '\0'); unget_stack += c; if (c == '\n') current_lineno--;}int table_input::get(){ int len = unget_stack.length(); if (len != 0) { unsigned char c = unget_stack[len - 1]; unget_stack.set_length(len - 1); if (c == '\n') current_lineno++; return c; } int c; for (;;) { switch (state) { case START: if ((c = getc(fp)) == '.') { if ((c = getc(fp)) == 'T') { if ((c = getc(fp)) == 'E') { if (compatible_flag) { state = END; return EOF; } else { c = getc(fp); if (c != EOF) ungetc(c, fp); if (c == EOF || c == ' ' || c == '\n') { state = END; return EOF; } state = REREAD_TE; return '.'; } } else { if (c != EOF) ungetc(c, fp); state = REREAD_T; return '.'; } } else { if (c != EOF) ungetc(c, fp); state = MIDDLE; return '.'; } } else if (c == EOF) { state = ERROR; return EOF; } else { if (c == '\n') current_lineno++; else { state = MIDDLE; if (c == '\0') { error("illegal input character code 0"); break; } } return c; } break; case MIDDLE: // handle line continuation if ((c = getc(fp)) == '\\') { c = getc(fp); if (c == '\n') c = getc(fp); // perhaps state ought to be START now else { if (c != EOF) ungetc(c, fp); c = '\\'; } } if (c == EOF) { state = ERROR; return EOF; } else { if (c == '\n') { state = START; current_lineno++; } else if (c == '\0') { error("illegal input character code 0"); break; } return c; } case REREAD_T: state = MIDDLE; return 'T'; case REREAD_TE: state = REREAD_E; return 'T'; case REREAD_E: state = MIDDLE; return 'E'; case END: case ERROR: return EOF; } }}void process_input_file(FILE *);void process_table(table_input &in);void process_input_file(FILE *fp){ enum { START, MIDDLE, HAD_DOT, HAD_T, HAD_TS, HAD_l, HAD_lf } state; state = START; int c; while ((c = getc(fp)) != EOF) switch (state) { case START: if (c == '.') state = HAD_DOT; else { if (c == '\n') current_lineno++; else state = MIDDLE; putchar(c); } break; case MIDDLE: if (c == '\n') { current_lineno++; state = START; } putchar(c); break; case HAD_DOT: if (c == 'T') state = HAD_T; else if (c == 'l') state = HAD_l; else { putchar('.'); putchar(c); if (c == '\n') { current_lineno++; state = START; } else state = MIDDLE; } break; case HAD_T: if (c == 'S') state = HAD_TS; else { putchar('.'); putchar('T'); putchar(c); if (c == '\n') { current_lineno++; state = START; } else state = MIDDLE; } break; case HAD_TS: if (c == ' ' || c == '\n' || compatible_flag) { putchar('.'); putchar('T'); putchar('S'); while (c != '\n') { if (c == EOF) { error("end of file at beginning of table"); return; } putchar(c); c = getc(fp); } putchar('\n'); current_lineno++; { table_input input(fp); process_table(input); set_troff_location(current_filename, current_lineno); if (input.ended()) { fputs(".TE", stdout); while ((c = getc(fp)) != '\n') { if (c == EOF) { putchar('\n'); return; } putchar(c); } putchar('\n'); current_lineno++; } } state = START; } else { fputs(".TS", stdout); putchar(c); state = MIDDLE; } break; case HAD_l: if (c == 'f') state = HAD_lf; else { putchar('.'); putchar('l'); putchar(c); if (c == '\n') { current_lineno++; state = START; } else state = MIDDLE; } break; case HAD_lf: if (c == ' ' || c == '\n' || compatible_flag) { string line; while (c != EOF) { line += c; if (c == '\n') { current_lineno++; break; } c = getc(fp); } line += '\0'; interpret_lf_args(line.contents()); printf(".lf%s", line.contents()); state = START; } else { fputs(".lf", stdout); putchar(c); state = MIDDLE; } break; default: assert(0); } switch(state) { case START: break; case MIDDLE: putchar('\n'); break; case HAD_DOT: fputs(".\n", stdout); break; case HAD_l: fputs(".l\n", stdout); break; case HAD_T: fputs(".T\n", stdout); break; case HAD_lf: fputs(".lf\n", stdout); break; case HAD_TS: fputs(".TS\n", stdout); break; } if (fp != stdin) fclose(fp);}struct options { unsigned flags; int linesize; char delim[2]; char tab_char; char decimal_point_char; options();};options::options(): flags(0), tab_char('\t'), decimal_point_char('.'), linesize(0){ delim[0] = delim[1] = '\0';}// Return non-zero if p and q are the same ignoring case.int strieq(const char *p, const char *q){ for (; cmlower(*p) == cmlower(*q); p++, q++) if (*p == '\0') return 1; return 0;}// return 0 if we should give up in this tableoptions *process_options(table_input &in){ options *opt = new options; string line; int level = 0; for (;;) { int c = in.get(); if (c == EOF) { int i = line.length(); while (--i >= 0) in.unget(line[i]); return opt; } if (c == '\n') { in.unget(c); int i = line.length(); while (--i >= 0) in.unget(line[i]); return opt; } else if (c == '(') level++; else if (c == ')') level--; else if (c == ';' && level == 0) { line += '\0'; break; } line += c; } if (line.empty()) return opt; char *p = &line[0]; for (;;) { while (csspace(*p) || *p == ',') p++; if (*p == '\0') break; char *q = p; while (*q != ' ' && *q != '\0' && *q != '\t' && *q != ',' && *q != '(') q++; char *arg = 0; if (*q != '(' && *q != '\0') *q++ = '\0'; while (csspace(*q)) q++; if (*q == '(') { *q++ = '\0'; arg = q; while (*q != ')' && *q != '\0') q++; if (*q == '\0') error("missing `)'"); else *q++ = '\0'; } if (*p == '\0') { if (arg) error("argument without option"); } else if (strieq(p, "tab")) { if (!arg) error("`tab' option requires argument in parentheses"); else { if (arg[0] == '\0' || arg[1] != '\0') error("argument to `tab' option must be a single character"); else opt->tab_char = arg[0]; } } else if (strieq(p, "linesize")) { if (!arg) error("`linesize' option requires argument in parentheses"); else { if (sscanf(arg, "%d", &opt->linesize) != 1) error("bad linesize `%s'", arg); else if (opt->linesize <= 0) { error("linesize must be positive"); opt->linesize = 0; } } } else if (strieq(p, "delim")) { if (!arg) error("`delim' option requires argument in parentheses"); else if (arg[0] == '\0' || arg[1] == '\0' || arg[2] != '\0') error("argument to `delim' option must be two characters"); else { opt->delim[0] = arg[0]; opt->delim[1] = arg[1]; } } else if (strieq(p, "center") || strieq(p, "centre")) { if (arg) error("`center' option does not take a argument"); opt->flags |= table::CENTER; } else if (strieq(p, "expand")) { if (arg) error("`expand' option does not take a argument"); opt->flags |= table::EXPAND; } else if (strieq(p, "box") || strieq(p, "frame")) { if (arg) error("`box' option does not take a argument"); opt->flags |= table::BOX; } else if (strieq(p, "doublebox") || strieq(p, "doubleframe")) { if (arg) error("`doublebox' option does not take a argument"); opt->flags |= table::DOUBLEBOX; } else if (strieq(p, "allbox")) { if (arg) error("`allbox' option does not take a argument"); opt->flags |= table::ALLBOX; } else if (strieq(p, "nokeep")) { if (arg) error("`nokeep' option does not take a argument"); opt->flags |= table::NOKEEP; } else if (strieq(p, "decimalpoint")) { if (!arg) error("`decimalpoint' option requires argument in parentheses"); else { if (arg[0] == '\0' || arg[1] != '\0') error("argument to `decimalpoint' option must be a single character"); else opt->decimal_point_char = arg[0]; } } else { error("unrecognised global option `%1'", p); // delete opt; // return 0; } p = q; } return opt;}entry_modifier::entry_modifier(): vertical_alignment(CENTER), zero_width(0), stagger(0){ vertical_spacing.inc = vertical_spacing.val = 0; point_size.inc = point_size.val = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -