📄 node.cc
字号:
tfont *current_tfont; int current_font_number; symbol *font_position; int nfont_positions; enum { TBUF_SIZE = 256 }; char tbuf[TBUF_SIZE]; int tbuf_len; int tbuf_kern; int begun_page; void do_motion(); void put(char c); void put(unsigned char c); void put(int i); void put(const char *s); void set_font(tfont *tf); void flush_tbuf();public: troff_output_file(); ~troff_output_file(); void trailer(vunits page_length); void put_char(charinfo *ci, tfont *tf); void put_char_width(charinfo *ci, tfont *tf, hunits w, hunits k); void right(hunits); void down(vunits); void moveto(hunits, vunits); void start_special(); void special_char(unsigned char c); void end_special(); void word_marker(); void really_transparent_char(unsigned char c); void really_print_line(hunits x, vunits y, node *n, vunits before, vunits after); void really_begin_page(int pageno, vunits page_length); void really_copy_file(hunits x, vunits y, const char *filename); void draw(char, hvpair *, int, font_size); int get_hpos() { return hpos; } int get_vpos() { return vpos; }};static void put_string(const char *s, FILE *fp){ for (; *s != '\0'; ++s) putc(*s, fp);}inline void troff_output_file::put(char c){ putc(c, fp);}inline void troff_output_file::put(unsigned char c){ putc(c, fp);}inline void troff_output_file::put(const char *s){ put_string(s, fp);}inline void troff_output_file::put(int i){ put_string(itoa(i), fp);}void troff_output_file::start_special(){ flush_tbuf(); do_motion(); put("x X ");}void troff_output_file::special_char(unsigned char c){ put(c); if (c == '\n') put('+');}void troff_output_file::end_special(){ put('\n');}inline void troff_output_file::moveto(hunits h, vunits v){ hpos = h.to_units(); vpos = v.to_units();}void troff_output_file::really_print_line(hunits x, vunits y, node *n, vunits before, vunits after){ moveto(x, y); while (n != 0) { n->tprint(this); n = n->next; } flush_tbuf(); // This ensures that transparent throughput will have a more predictable // position. do_motion(); force_motion = 1; hpos = 0; put('n'); put(before.to_units()); put(' '); put(after.to_units()); put('\n');}inline void troff_output_file::word_marker(){ flush_tbuf(); put('w');}inline void troff_output_file::right(hunits n){ hpos += n.to_units();}inline void troff_output_file::down(vunits n){ vpos += n.to_units();}void troff_output_file::do_motion(){ if (force_motion) { put('V'); put(vpos); put('\n'); put('H'); put(hpos); put('\n'); } else { if (hpos != output_hpos) { units n = hpos - output_hpos; if (n > 0 && n < hpos) { put('h'); put(n); } else { put('H'); put(hpos); } put('\n'); } if (vpos != output_vpos) { units n = vpos - output_vpos; if (n > 0 && n < vpos) { put('v'); put(n); } else { put('V'); put(vpos); } put('\n'); } } output_vpos = vpos; output_hpos = hpos; force_motion = 0;}void troff_output_file::flush_tbuf(){ if (tbuf_len == 0) return; if (tbuf_kern == 0) put('t'); else { put('u'); put(tbuf_kern); put(' '); } for (int i = 0; i < tbuf_len; i++) put(tbuf[i]); put('\n'); tbuf_len = 0;}void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w, hunits k){ if (tf != current_tfont) { flush_tbuf(); set_font(tf); } char c = ci->get_ascii_code(); int kk = k.to_units(); if (c == '\0') { flush_tbuf(); do_motion(); if (ci->numbered()) { put('N'); put(ci->get_number()); } else { put('C'); const char *s = ci->nm.contents(); if (s[1] == 0) { put('\\'); put(s[0]); } else put(s); } put('\n'); hpos += w.to_units() + kk; } else if (tcommand_flag) { if (tbuf_len > 0 && hpos == output_hpos && vpos == output_vpos && kk == tbuf_kern && tbuf_len < TBUF_SIZE) { tbuf[tbuf_len++] = c; output_hpos += w.to_units() + kk; hpos = output_hpos; return; } flush_tbuf(); do_motion(); tbuf[tbuf_len++] = c; output_hpos += w.to_units() + kk; tbuf_kern = kk; hpos = output_hpos; } else { // flush_tbuf(); int n = hpos - output_hpos; if (vpos == output_vpos && n > 0 && n < 100 && !force_motion) { put(char(n/10 + '0')); put(char(n%10 + '0')); put(c); output_hpos = hpos; } else { do_motion(); put('c'); put(c); } hpos += w.to_units() + kk; }}void troff_output_file::put_char(charinfo *ci, tfont *tf){ flush_tbuf(); if (tf != current_tfont) set_font(tf); char c = ci->get_ascii_code(); if (c == '\0') { do_motion(); if (ci->numbered()) { put('N'); put(ci->get_number()); } else { put('C'); const char *s = ci->nm.contents(); if (s[1] == 0) { put('\\'); put(s[0]); } else put(s); } put('\n'); } else { int n = hpos - output_hpos; if (vpos == output_vpos && n > 0 && n < 100) { put(char(n/10 + '0')); put(char(n%10 + '0')); put(c); output_hpos = hpos; } else { do_motion(); put('c'); put(c); } }}void troff_output_file::set_font(tfont *tf){ if (current_tfont == tf) return; int n = tf->get_input_position(); symbol nm = tf->get_name(); if (n >= nfont_positions || font_position[n] != nm) { put("x font "); put(n); put(' '); put(nm.contents()); put('\n'); if (n >= nfont_positions) { int old_nfont_positions = nfont_positions; symbol *old_font_position = font_position; nfont_positions *= 3; nfont_positions /= 2; if (nfont_positions <= n) nfont_positions = n + 10; font_position = new symbol[nfont_positions]; memcpy(font_position, old_font_position, old_nfont_positions*sizeof(symbol)); a_delete old_font_position; } font_position[n] = nm; } if (current_font_number != n) { put('f'); put(n); put('\n'); current_font_number = n; } int size = tf->get_size().to_scaled_points(); if (current_size != size) { put('s'); put(size); put('\n'); current_size = size; } int slant = tf->get_slant(); if (current_slant != slant) { put("x Slant "); put(slant); put('\n'); current_slant = slant; } int height = tf->get_height(); if (current_height != height) { put("x Height "); put(height == 0 ? current_size : height); put('\n'); current_height = height; } current_tfont = tf;}void troff_output_file::draw(char code, hvpair *point, int npoints, font_size fsize){ flush_tbuf(); do_motion(); int size = fsize.to_scaled_points(); if (current_size != size) { put('s'); put(size); put('\n'); current_size = size; current_tfont = 0; } put('D'); put(code); int i; if (code == 'c') { put(' '); put(point[0].h.to_units()); } else for (i = 0; i < npoints; i++) { put(' '); put(point[i].h.to_units()); put(' '); put(point[i].v.to_units()); } for (i = 0; i < npoints; i++) output_hpos += point[i].h.to_units(); hpos = output_hpos; if (code != 'e') { for (i = 0; i < npoints; i++) output_vpos += point[i].v.to_units(); vpos = output_vpos; } put('\n');}void troff_output_file::really_begin_page(int pageno, vunits page_length){ flush_tbuf(); if (begun_page) { if (page_length > V0) { put('V'); put(page_length.to_units()); put('\n'); } } else begun_page = 1; current_tfont = 0; current_font_number = -1; current_size = 0; // current_height = 0; // current_slant = 0; hpos = 0; vpos = 0; output_hpos = 0; output_vpos = 0; force_motion = 1; for (int i = 0; i < nfont_positions; i++) font_position[i] = NULL_SYMBOL; put('p'); put(pageno); put('\n');}void troff_output_file::really_copy_file(hunits x, vunits y, const char *filename){ moveto(x, y); flush_tbuf(); do_motion(); errno = 0; FILE *ifp = fopen(filename, "r"); if (ifp == 0) error("can't open `%1': %2", filename, strerror(errno)); else { int c; while ((c = getc(ifp)) != EOF) put(char(c)); fclose(ifp); } force_motion = 1; current_size = 0; current_tfont = 0; current_font_number = -1; for (int i = 0; i < nfont_positions; i++) font_position[i] = NULL_SYMBOL;} void troff_output_file::really_transparent_char(unsigned char c){ put(c);}troff_output_file::~troff_output_file(){ a_delete font_position;}void troff_output_file::trailer(vunits page_length){ flush_tbuf(); if (page_length > V0) { put("x trailer\n"); put('V'); put(page_length.to_units()); put('\n'); } put("x stop\n");}troff_output_file::troff_output_file(): current_height(0), current_slant(0), tbuf_len(0), nfont_positions(10), begun_page(0){ font_position = new symbol[nfont_positions]; put("x T "); put(device); put('\n'); put("x res "); put(units_per_inch); put(' '); put(hresolution); put(' '); put(vresolution); put('\n'); put("x init\n");}/* output_file */output_file *the_output = 0;output_file::output_file(){}output_file::~output_file(){}void output_file::trailer(vunits){}real_output_file::real_output_file(): printing(0){ if (pipe_command) { if ((fp = popen(pipe_command, "w")) != 0) { piped = 1; return; } error("pipe open failed: %1", strerror(errno)); } piped = 0; fp = stdout;}real_output_file::~real_output_file(){ if (!fp) return; // To avoid looping, set fp to 0 before calling fatal(). if (ferror(fp) || fflush(fp) < 0) { fp = 0; fatal("error writing output file"); } if (piped) { int result = pclose(fp); fp = 0; if (result < 0) fatal("pclose failed"); if ((result & 0x7f) != 0) error("output process `%1' got fatal signal %2", pipe_command, result & 0x7f); else { int exit_status = (result >> 8) & 0xff; if (exit_status != 0) error("output process `%1' exited with status %2", pipe_command, exit_status); } } else if (fclose(fp) < 0) { fp = 0; fatal("error closing output file"); }}void real_output_file::flush(){ if (fflush(fp) < 0) fatal("error writing output file");}int real_output_file::is_printing(){ return printing;}void real_output_file::begin_page(int pageno, vunits page_length){ printing = in_output_page_list(pageno); if (printing) really_begin_page(pageno, page_length);}void real_output_file::copy_file(hunits x, vunits y, const char *filename){ if (printing) really_copy_file(x, y, filename);}void real_output_file::transparent_char(unsigned char c){ if (printing) really_transparent_char(c);}void real_output_file::print_line(hunits x, vunits y, node *n, vunits before, vunits after){ if (printing) really_print_line(x, y, n, before, after); delete_node_list(n);}void real_output_file::really_copy_file(hunits, vunits, const char *){ // do nothing}/* ascii_output_file */void ascii_output_file::really_transparent_char(unsigned char c){ putc(c, fp);}void ascii_output_file::really_print_line(hunits, vunits, node *n, vunits, vunits){ while (n != 0) { n->ascii_print(this); n = n->next; } fputc('\n', fp);}void ascii_output_file::really_begin_page(int /*pageno*/, vunits /*page_length*/){ fputs("<beginning of page>\n", fp);}ascii_output_file::ascii_output_file(){}/* suppress_output_file */suppress_output_file::suppress_output_file(){}void suppress_output_file::really_print_line(hunits, vunits, node *, vunits, vunits){}void suppress_output_file::really_begin_page(int, vunits){}void suppress_output_file::really_transparent_char(unsigned char){}/* glyphs, ligatures, kerns, discretionary breaks */class glyph_node : public node { static glyph_node *free_list;protected: charinfo *ci; tfont *tf;#ifdef STORE_WIDTH hunits wid; glyph_node(charinfo *, tfont *, hunits, node * = 0);#endifpublic: void *operator new(size_t); void operator delete(void *); glyph_node(charinfo *, tfont *, node * = 0); ~glyph_node() {} node *copy(); node *merge_glyph_node(glyph_node *); node *merge_self(node *); hunits width(); node *last_char_node(); units size(); void vertical_extent(vunits *, vunits *); hunits subscript_correction(); hunits italic_correction(); hunits left_italic_correction(); hunits skew(); hyphenation_type get_hyphenation_type(); tfont *get_tfont(); void tprint(troff_output_file *); void zero_width_tprint(troff_output_file *); hyphen_list *get_hyphen_list(hyphen_list *ss = 0); node *add_self(node *, hyphen_list **); int ends_sentence(); int overlaps_vertically(); int overlaps_horizontally(); void ascii_print(ascii_output_file *); void asciify(macro *); int character_type(); int same(node *); const char *type();};glyph_node *glyph_node::free_list = 0;class ligature_node : public glyph_node { node *n1; node *n2;#ifdef STORE_WIDTH ligature_node(charinfo *, tfont *, hunits, node *gn1, node *gn2, node *x = 0);#endifpublic: void *operator new(size_t); void operator delete(void *); ligature_node(charinfo *, tfont *, node *gn1, node *gn2, node *x = 0); ~ligature_node(); node *copy(); node *add_self(node *, hyphen_list **); hyphen_list *get_hyphen_list(hyphen_list *ss = 0); void ascii_print(ascii_output_file *); void asciify(macro *); int same(node *); const char *type();};class kern_pair_node : public node {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -