📄 env.cc
字号:
case TAB_NONE: return; case TAB_LEFT: add_node(make_tab_node(d)); return; case TAB_RIGHT: case TAB_CENTER: tab_width = 0; tab_distance = d; tab_contents = 0; current_tab = t; tab_field_spaces = 0; return; default: assert(0); }}void environment::start_field(){ assert(!current_field); hunits d; if (distance_to_next_tab(&d) != TAB_NONE) { pre_field_width = get_text_length(); field_distance = d; current_field = 1; field_spaces = 0; tab_field_spaces = 0; for (node *p = line; p; p = p->next) if (p->nspaces()) { p->freeze_space(); space_total--; } tab_precedes_field = current_tab != TAB_NONE; } else error("zero field width");}void environment::wrap_up_field(){ if (!current_tab && field_spaces == 0) add_padding(); hunits padding = field_distance - (get_text_length() - pre_field_width); if (current_tab && tab_field_spaces != 0) { hunits tab_padding = scale(padding, tab_field_spaces, field_spaces + tab_field_spaces); padding -= tab_padding; distribute_space(tab_contents, tab_field_spaces, tab_padding, 1); tab_field_spaces = 0; tab_width += tab_padding; } if (field_spaces != 0) { distribute_space(line, field_spaces, padding, 1); width_total += padding; if (current_tab) { // the start of the tab has been moved to the right by padding, so tab_distance -= padding; if (tab_distance <= H0) { // use the next tab stop instead current_tab = tabs.distance_to_next_tab(get_input_line_position() - tab_width, &tab_distance); if (current_tab == TAB_NONE || current_tab == TAB_LEFT) { width_total += tab_width; if (current_tab == TAB_LEFT) { line = make_tab_node(tab_distance, line); width_total += tab_distance; current_tab = TAB_NONE; } if (tab_contents != 0) { for (node *tem = tab_contents; tem->next != 0; tem = tem->next) ; tem->next = line; line = tab_contents; tab_contents = 0; } tab_width = H0; tab_distance = H0; } } } } current_field = 0;}void environment::add_padding(){ if (current_tab) { tab_contents = new space_node(H0, tab_contents); tab_field_spaces++; } else { if (line == 0) start_line(); line = new space_node(H0, line); field_spaces++; }}typedef int (environment::*INT_FUNCP)();typedef vunits (environment::*VUNITS_FUNCP)();typedef hunits (environment::*HUNITS_FUNCP)();typedef const char *(environment::*STRING_FUNCP)();class int_env_reg : public reg { INT_FUNCP func; public: int_env_reg(INT_FUNCP); const char *get_string(); int get_value(units *val);};class vunits_env_reg : public reg { VUNITS_FUNCP func; public: vunits_env_reg(VUNITS_FUNCP f); const char *get_string(); int get_value(units *val);};class hunits_env_reg : public reg { HUNITS_FUNCP func; public: hunits_env_reg(HUNITS_FUNCP f); const char *get_string(); int get_value(units *val);};class string_env_reg : public reg { STRING_FUNCP func;public: string_env_reg(STRING_FUNCP); const char *get_string();};int_env_reg::int_env_reg(INT_FUNCP f) : func(f){}int int_env_reg::get_value(units *val){ *val = (curenv->*func)(); return 1;}const char *int_env_reg::get_string(){ return itoa((curenv->*func)());} vunits_env_reg::vunits_env_reg(VUNITS_FUNCP f) : func(f){}int vunits_env_reg::get_value(units *val){ *val = (curenv->*func)().to_units(); return 1;}const char *vunits_env_reg::get_string(){ return itoa((curenv->*func)().to_units());}hunits_env_reg::hunits_env_reg(HUNITS_FUNCP f) : func(f){}int hunits_env_reg::get_value(units *val){ *val = (curenv->*func)().to_units(); return 1;}const char *hunits_env_reg::get_string(){ return itoa((curenv->*func)().to_units());}string_env_reg::string_env_reg(STRING_FUNCP f) : func(f){}const char *string_env_reg::get_string(){ return (curenv->*func)();}class horizontal_place_reg : public general_reg {public: horizontal_place_reg(); int get_value(units *); void set_value(units);};horizontal_place_reg::horizontal_place_reg(){}int horizontal_place_reg::get_value(units *res){ *res = curenv->get_input_line_position().to_units(); return 1;}void horizontal_place_reg::set_value(units n){ curenv->set_input_line_position(hunits(n));}const char *environment::get_font_family_string(){ return family->nm.contents();}const char *environment::get_name_string(){ return name.contents();}// Convert a quantity in scaled points to ascii decimal fraction.const char *sptoa(int sp){ assert(sp > 0); assert(sizescale > 0); if (sizescale == 1) return itoa(sp); if (sp % sizescale == 0) return itoa(sp/sizescale); // See if 1/sizescale is exactly representable as a decimal fraction, // ie its only prime factors are 2 and 5. int n = sizescale; int power2 = 0; while ((n & 1) == 0) { n >>= 1; power2++; } int power5 = 0; while ((n % 5) == 0) { n /= 5; power5++; } if (n == 1) { int decimal_point = power5 > power2 ? power5 : power2; if (decimal_point <= 10) { int factor = 1; int t; for (t = decimal_point - power2; --t >= 0;) factor *= 2; for (t = decimal_point - power5; --t >= 0;) factor *= 5; if (factor == 1 || sp <= INT_MAX/factor) return iftoa(sp*factor, decimal_point); } } double s = double(sp)/double(sizescale); double factor = 10.0; double val = s; int decimal_point = 0; do { double v = ceil(s*factor); if (v > INT_MAX) break; val = v; factor *= 10.0; } while (++decimal_point < 10); return iftoa(int(val), decimal_point);}const char *environment::get_point_size_string(){ return sptoa(curenv->get_point_size());}const char *environment::get_requested_point_size_string(){ return sptoa(curenv->get_requested_point_size());}#define init_int_env_reg(name, func) \ number_reg_dictionary.define(name, new int_env_reg(&environment::func))#define init_vunits_env_reg(name, func) \ number_reg_dictionary.define(name, new vunits_env_reg(&environment::func))#define init_hunits_env_reg(name, func) \ number_reg_dictionary.define(name, new hunits_env_reg(&environment::func))#define init_string_env_reg(name, func) \ number_reg_dictionary.define(name, new string_env_reg(&environment::func))void init_env_requests(){ init_request("it", input_trap); init_request("ad", adjust); init_request("na", no_adjust); init_request("ev", environment_switch); init_request("lt", title_length); init_request("ps", point_size); init_request("ft", font_change); init_request("fam", family_change); init_request("ss", space_size); init_request("fi", fill); init_request("nf", no_fill); init_request("ce", center); init_request("rj", right_justify); init_request("vs", vertical_spacing); init_request("ls", line_spacing); init_request("ll", line_length); init_request("in", indent); init_request("ti", temporary_indent); init_request("ul", underline); init_request("cu", underline); init_request("cc", control_char); init_request("c2", no_break_control_char); init_request("br", break_request); init_request("tl", title); init_request("ta", set_tabs); init_request("fc", field_characters); init_request("mc", margin_character); init_request("nn", no_number); init_request("nm", number_lines); init_request("tc", tab_character); init_request("lc", leader_character); init_request("hy", hyphenate_request); init_request("hc", hyphen_char); init_request("nh", no_hyphenate); init_request("hlm", hyphen_line_max_request);#ifdef WIDOW_CONTROL init_request("wdc", widow_control_request);#endif /* WIDOW_CONTROL */#if 0 init_request("tas", tabs_save); init_request("tar", tabs_restore);#endif init_request("hys", hyphenation_space_request); init_request("hym", hyphenation_margin_request); init_int_env_reg(".f", get_font); init_int_env_reg(".b", get_bold); init_hunits_env_reg(".i", get_indent); init_hunits_env_reg(".in", get_saved_indent); init_int_env_reg(".j", get_adjust_mode); init_hunits_env_reg(".k", get_text_length); init_hunits_env_reg(".l", get_line_length); init_hunits_env_reg(".ll", get_saved_line_length); init_int_env_reg(".L", get_line_spacing); init_hunits_env_reg(".n", get_prev_text_length); init_string_env_reg(".s", get_point_size_string); init_string_env_reg(".sr", get_requested_point_size_string); init_int_env_reg(".ps", get_point_size); init_int_env_reg(".psr", get_requested_point_size); init_int_env_reg(".u", get_fill); init_vunits_env_reg(".v", get_vertical_spacing); init_hunits_env_reg(".w", get_prev_char_width); init_int_env_reg(".ss", get_space_size); init_int_env_reg(".sss", get_sentence_space_size); init_string_env_reg(".fam", get_font_family_string); init_string_env_reg(".ev", get_name_string); init_int_env_reg(".hy", get_hyphenation_flags); init_int_env_reg(".hlm", get_hyphen_line_max); init_int_env_reg(".hlc", get_hyphen_line_count); init_hunits_env_reg(".lt", get_title_length); init_string_env_reg(".tabs", get_tabs); init_hunits_env_reg(".csk", get_prev_char_skew); init_vunits_env_reg(".cht", get_prev_char_height); init_vunits_env_reg(".cdp", get_prev_char_depth); init_int_env_reg(".ce", get_center_lines); init_int_env_reg(".rj", get_right_justify_lines); init_hunits_env_reg(".hys", get_hyphenation_space); init_hunits_env_reg(".hym", get_hyphenation_margin); number_reg_dictionary.define("ln", new variable_reg(&next_line_number)); number_reg_dictionary.define("ct", new variable_reg(&ct_reg_contents)); number_reg_dictionary.define("sb", new variable_reg(&sb_reg_contents)); number_reg_dictionary.define("st", new variable_reg(&st_reg_contents)); number_reg_dictionary.define("rsb", new variable_reg(&rsb_reg_contents)); number_reg_dictionary.define("rst", new variable_reg(&rst_reg_contents)); number_reg_dictionary.define("ssc", new variable_reg(&ssc_reg_contents)); number_reg_dictionary.define("skw", new variable_reg(&skw_reg_contents)); number_reg_dictionary.define("hp", new horizontal_place_reg);}// Hyphenation - TeX's hyphenation algorithm with a less fancy implementation.struct trie_node;class trie { trie_node *tp; virtual void do_match(int len, void *val) = 0; virtual void do_delete(void *) = 0; void delete_trie_node(trie_node *);public: trie() : tp(0) {} virtual ~trie(); // virtual to shut up g++ void insert(const char *, int, void *); // find calls do_match for each match it finds void find(const char *pat, int patlen); void clear();};class hyphen_trie : private trie { int *h; void do_match(int i, void *v); void do_delete(void *v); void insert_pattern(const char *pat, int patlen, int *num);public: hyphen_trie() {} ~hyphen_trie() {} void hyphenate(const char *word, int len, int *hyphens); void read_patterns_file(const char *name);};struct hyphenation_language { symbol name; dictionary exceptions; hyphen_trie patterns; hyphenation_language(symbol nm) : name(nm), exceptions(501) {} ~hyphenation_language() { }};dictionary language_dictionary(5);hyphenation_language *current_language = 0;static void set_hyphenation_language(){ symbol nm = get_name(1); if (!nm.is_null()) { current_language = (hyphenation_language *)language_dictionary.lookup(nm); if (!current_language) { current_language = new hyphenation_language(nm); (void)language_dictionary.lookup(nm, (void *)current_language); } } skip_line();}const int WORD_MAX = 1024;static void hyphen_word(){ if (!current_language) { error("no current hyphenation language"); skip_line(); return; } char buf[WORD_MAX + 1]; unsigned char pos[WORD_MAX + 2]; for (;;) { tok.skip(); if (tok.newline() || tok.eof()) break; int i = 0; int npos = 0; while (i < WORD_MAX && !tok.space() && !tok.newline() && !tok.eof()) { charinfo *ci = tok.get_char(1); if (ci == 0) { skip_line(); return; } tok.next(); if (ci->get_ascii_code() == '-') { if (i > 0 && (npos == 0 || pos[npos - 1] != i)) pos[npos++] = i; } else { int c = ci->get_hyphenation_code(); if (c == 0) break; buf[i++] = c; } } if (i > 0) { pos[npos] = 0; buf[i] = 0; unsigned char *tem = new unsigned char[npos + 1]; memcpy(tem, pos, npos+1); tem = (unsigned char *)current_language->exceptions.lookup(symbol(buf), tem); if (tem) a_delete tem; } } skip_line();}struct trie_node { char c; trie_node *down; trie_node *right; void *val; trie_node(char, trie_node *);};trie_node::trie_node(char ch, trie_node *p) : c(ch), right(p), down(0), val(0){}trie::~trie(){ clear();}void trie::clear(){ delete_trie_node(tp); tp = 0;}void trie::delete_trie_node(trie_node *p){ if (p) { delete_trie_node(p->down); delete_trie_node(p->right); if (p->val) do_delete(p->val); delete p; }}void trie::insert(const char *pat, int patlen, void *val){ trie_node **p = &tp; assert(patlen > 0 && pat != 0); for (;;) { while (*p != 0 && (*p)->c < pat[0]) p = &((*p)->right); if (*p == 0 || (*p)->c != pat[0]) *p = new trie_node(pat[0], *p); if (--patlen == 0) { (*p)->val = val; break; } ++pat; p = &((*p)->down); }}void trie::find(const char *pat, int patlen){ trie_node *p = tp; for (int i = 0; p != 0 && i < patlen; i++) { while (p != 0 && p->c < pat[i]) p = p->right; if (p != 0 && p->c == pat[i]) { if (p->val != 0) do_match(i+1, p->val); p = p->down; } else break; }}struct operation { operation *next; short distance; short num; operation(int, int, operation *);};operation::operation(int i, int j, operation *op): num(i), distance(j), next(op){}void hyphen_trie::insert_pattern(const char *pat, int patlen, int *num){ operation *op = 0; for (int i = 0; i < patlen+1; i++) if
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -