📄 text.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 "eqn.h"#include "pbox.h"#include "ptable.h"class char_box : public simple_box { unsigned char c; char next_is_italic; char prev_is_italic;public: char_box(unsigned char); void debug_print(); void output(); int is_char(); int left_is_italic(); int right_is_italic(); void hint(unsigned); void handle_char_type(int, int);};class special_char_box : public simple_box { char *s;public: special_char_box(const char *); ~special_char_box(); void output(); void debug_print(); int is_char(); void handle_char_type(int, int);};const char *spacing_type_table[] = { "ordinary", "operator", "binary", "relation", "opening", "closing", "punctuation", "inner", "suppress", 0,};const int DIGIT_TYPE = 0;const int LETTER_TYPE = 1;const char *font_type_table[] = { "digit", "letter", 0,};struct char_info { int spacing_type; int font_type; char_info();};char_info::char_info(): spacing_type(ORDINARY_TYPE), font_type(DIGIT_TYPE){}static char_info char_table[256];declare_ptable(char_info)implement_ptable(char_info)PTABLE(char_info) special_char_table;static int get_special_char_spacing_type(const char *ch){ char_info *p = special_char_table.lookup(ch); return p ? p->spacing_type : ORDINARY_TYPE;}static int get_special_char_font_type(const char *ch){ char_info *p = special_char_table.lookup(ch); return p ? p->font_type : DIGIT_TYPE;}static void set_special_char_type(const char *ch, int st, int ft){ char_info *p = special_char_table.lookup(ch); if (!p) { p = new char_info; special_char_table.define(ch, p); } if (st >= 0) p->spacing_type = st; if (ft >= 0) p->font_type = ft;}void init_char_table(){ set_special_char_type("pl", 2, -1); // binary set_special_char_type("mi", 2, -1); set_special_char_type("eq", 3, -1); // relation set_special_char_type("<=", 3, -1); set_special_char_type(">=", 3, -1); char_table['}'].spacing_type = 5; // closing char_table[')'].spacing_type = 5; char_table[']'].spacing_type = 5; char_table['{'].spacing_type = 4; // opening char_table['('].spacing_type = 4; char_table['['].spacing_type = 4; char_table[','].spacing_type = 6; // punctuation char_table[';'].spacing_type = 6; char_table[':'].spacing_type = 6; char_table['.'].spacing_type = 6; char_table['>'].spacing_type = 3; char_table['<'].spacing_type = 3; char_table['*'].spacing_type = 2; // binary for (int i = 0; i < 256; i++) if (csalpha(i)) char_table[i].font_type = LETTER_TYPE;}static int lookup_spacing_type(const char *type){ for (int i = 0; spacing_type_table[i] != 0; i++) if (strcmp(spacing_type_table[i], type) == 0) return i; return -1;}static int lookup_font_type(const char *type){ for (int i = 0; font_type_table[i] != 0; i++) if (strcmp(font_type_table[i], type) == 0) return i; return -1;}void box::set_spacing_type(char *type){ int t = lookup_spacing_type(type); if (t < 0) error("unrecognised type `%1'", type); else spacing_type = t; a_delete type;}char_box::char_box(unsigned char cc): c(cc), prev_is_italic(0), next_is_italic(0){ spacing_type = char_table[c].spacing_type;}void char_box::hint(unsigned flags){ if (flags & HINT_PREV_IS_ITALIC) prev_is_italic = 1; if (flags & HINT_NEXT_IS_ITALIC) next_is_italic = 1;}void char_box::output(){ int font_type = char_table[c].font_type; if (font_type != LETTER_TYPE) printf("\\f[%s]", current_roman_font); if (!prev_is_italic) fputs("\\,", stdout); if (c == '\\') fputs("\\e", stdout); else putchar(c); if (!next_is_italic) fputs("\\/", stdout); else fputs("\\&", stdout); // suppress ligaturing and kerning if (font_type != LETTER_TYPE) fputs("\\fP", stdout);}int char_box::left_is_italic(){ int font_type = char_table[c].font_type; return font_type == LETTER_TYPE;}int char_box::right_is_italic(){ int font_type = char_table[c].font_type; return font_type == LETTER_TYPE;}int char_box::is_char(){ return 1;}void char_box::debug_print(){ if (c == '\\') { putc('\\', stderr); putc('\\', stderr); } else putc(c, stderr);}special_char_box::special_char_box(const char *t){ s = strsave(t); spacing_type = get_special_char_spacing_type(s);}special_char_box::~special_char_box(){ a_delete s;}void special_char_box::output(){ int font_type = get_special_char_font_type(s); if (font_type != LETTER_TYPE) printf("\\f[%s]", current_roman_font); printf("\\,\\[%s]\\/", s); if (font_type != LETTER_TYPE) printf("\\fP");}int special_char_box::is_char(){ return 1;}void special_char_box::debug_print(){ fprintf(stderr, "\\[%s]", s);}void char_box::handle_char_type(int st, int ft){ if (st >= 0) char_table[c].spacing_type = st; if (ft >= 0) char_table[c].font_type = ft;}void special_char_box::handle_char_type(int st, int ft){ set_special_char_type(s, st, ft);}void set_char_type(const char *type, char *ch){ assert(ch != 0); int st = lookup_spacing_type(type); int ft = lookup_font_type(type); if (st < 0 && ft < 0) { error("bad character type `%1'", type); a_delete ch; return; } box *b = split_text(ch); b->handle_char_type(st, ft); delete b;}/* We give primes special treatment so that in ``x' sub 2'', the ``2''will be tucked under the prime */class prime_box : public pointer_box { box *pb;public: prime_box(box *); ~prime_box(); int compute_metrics(int style); void output(); void compute_subscript_kern(); void debug_print(); void handle_char_type(int, int);};box *make_prime_box(box *pp){ return new prime_box(pp);}prime_box::prime_box(box *pp) : pointer_box(pp){ pb = new special_char_box("fm");}prime_box::~prime_box(){ delete pb;}int prime_box::compute_metrics(int style){ int res = p->compute_metrics(style); pb->compute_metrics(style); printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]" "+\\n[" WIDTH_FORMAT "]\n", uid, p->uid, pb->uid); printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]" ">?\\n[" HEIGHT_FORMAT "]\n", uid, p->uid, pb->uid); printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]" ">?\\n[" DEPTH_FORMAT "]\n", uid, p->uid, pb->uid); return res;}void prime_box::compute_subscript_kern(){ p->compute_subscript_kern(); printf(".nr " SUB_KERN_FORMAT " 0\\n[" WIDTH_FORMAT "]" "+\\n[" SUB_KERN_FORMAT "]>?0\n", uid, pb->uid, p->uid);}void prime_box::output(){ p->output(); pb->output();}void prime_box::handle_char_type(int st, int ft){ p->handle_char_type(st, ft); pb->handle_char_type(st, ft);}void prime_box::debug_print(){ p->debug_print(); putc('\'', stderr);}box *split_text(char *text){ list_box *lb = 0; box *fb = 0; char *s = text; while (*s != '\0') { char c = *s++; box *b = 0; switch (c) { case '+': b = new special_char_box("pl"); break; case '-': b = new special_char_box("mi"); break; case '=': b = new special_char_box("eq"); break; case '\'': b = new special_char_box("fm"); break; case '<': if (*s == '=') { b = new special_char_box("<="); s++; break; } goto normal_char; case '>': if (*s == '=') { b = new special_char_box(">="); s++; break; } goto normal_char; case '\\': if (*s == '\0') { lex_error("bad escape"); break; } c = *s++; switch (c) { case '(': { char buf[3]; if (*s != '\0') { buf[0] = *s++; if (*s != '\0') { buf[1] = *s++; buf[2] = '\0'; b = new special_char_box(buf); } else { lex_error("bad escape"); } } else { lex_error("bad escape"); } } break; case '[': { char *ch = s; while (*s != ']' && *s != '\0') s++; if (*s == '\0') lex_error("bad escape"); else { *s++ = '\0'; b = new special_char_box(ch); } } break; case 'f': case 'g': case 'k': case 'n': case '*': { char *escape_start = s - 2; switch (*s) { case '(': if (*++s != '\0') ++s; break; case '[': for (++s; *s != '\0' && *s != ']'; s++) ; break; } if (*s == '\0') lex_error("bad escape"); else { ++s; char *buf = new char[s - escape_start + 1]; memcpy(buf, escape_start, s - escape_start); buf[s - escape_start] = '\0'; b = new quoted_text_box(buf); } } break; case '-': case '_': { char buf[2]; buf[0] = c; buf[1] = '\0'; b = new special_char_box(buf); } break; case '`': b = new special_char_box("ga"); break; case '\'': b = new special_char_box("aa"); break; case 'e': case '\\': b = new char_box('\\'); break; case '^': case '|': case '0': { char buf[3]; buf[0] = '\\'; buf[1] = c; buf[2] = '\0'; b = new quoted_text_box(strsave(buf)); break; } default: lex_error("unquoted escape"); b = new quoted_text_box(strsave(s - 2)); s = strchr(s, '\0'); break; } break; default: normal_char: b = new char_box(c); break; } while (*s == '\'') { if (b == 0) b = new quoted_text_box(0); b = new prime_box(b); s++; } if (b != 0) { if (lb != 0) lb->append(b); else if (fb != 0) { lb = new list_box(fb); lb->append(b); } else fb = b; } } delete text; if (lb != 0) return lb; else if (fb != 0) return fb; else return new quoted_text_box(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -