📄 env.cc
字号:
if (tok.ch() == 0) error("bad control character"); else curenv->control_char = tok.ch(); } skip_line();}void no_break_control_char(){ curenv->no_break_control_char = '\''; if (has_arg()) { if (tok.ch() == 0) error("bad control character"); else curenv->no_break_control_char = tok.ch(); } skip_line();}void margin_character(){ charinfo *ci = get_optional_char(); if (ci) { node *nd = curenv->make_char_node(ci); if (nd) { delete curenv->margin_character_node; curenv->margin_character_node = nd; curenv->margin_character_flags = (MARGIN_CHARACTER_ON |MARGIN_CHARACTER_NEXT); hunits d; if (has_arg() && get_hunits(&d, 'm')) curenv->margin_character_distance = d; } } else { curenv->margin_character_flags &= ~MARGIN_CHARACTER_ON; if (curenv->margin_character_flags == 0) { delete curenv->margin_character_node; curenv->margin_character_node = 0; } } skip_line();}void number_lines(){ delete_node_list(curenv->numbering_nodes); curenv->numbering_nodes = 0; if (has_arg()) { node *nd = 0; for (int i = '9'; i >= '0'; i--) { node *tem = make_node(charset_table[i], curenv); if (!tem) { skip_line(); return; } tem->next = nd; nd = tem; } curenv->numbering_nodes = nd; curenv->line_number_digit_width = env_digit_width(curenv); int n; if (!tok.delimiter()) { if (get_integer(&n, next_line_number)) { next_line_number = n; if (next_line_number < 0) { warning(WARN_RANGE, "negative line number"); next_line_number = 0; } } } else while (!tok.space() && !tok.newline() && !tok.eof()) tok.next(); if (has_arg()) { if (!tok.delimiter()) { if (get_integer(&n)) { if (n <= 0) { warning(WARN_RANGE, "negative or zero line number multiple"); } else curenv->line_number_multiple = n; } } else while (!tok.space() && !tok.newline() && !tok.eof()) tok.next(); if (has_arg()) { if (!tok.delimiter()) { if (get_integer(&n)) curenv->number_text_separation = n; } else while (!tok.space() && !tok.newline() && !tok.eof()) tok.next(); if (has_arg() && !tok.delimiter() && get_integer(&n)) curenv->line_number_indent = n; } } } skip_line();}void no_number(){ int n; if (has_arg() && get_integer(&n)) curenv->no_number_count = n > 0 ? n : 0; else curenv->no_number_count = 1; skip_line();}void no_hyphenate(){ curenv->hyphenation_flags = 0; skip_line();}void hyphenate_request(){ int n; if (has_arg() && get_integer(&n)) curenv->hyphenation_flags = n; else curenv->hyphenation_flags = 1; skip_line();}void hyphen_char(){ curenv->hyphen_indicator_char = get_optional_char(); skip_line();}void hyphen_line_max_request(){ int n; if (has_arg() && get_integer(&n)) curenv->hyphen_line_max = n; else curenv->hyphen_line_max = -1; skip_line();}void environment::interrupt(){ if (!dummy) { add_node(new transparent_dummy_node); interrupted = 1; }}void environment::newline(){ if (underline_lines > 0) { if (--underline_lines == 0) { prev_fontno = fontno; fontno = pre_underline_fontno; } } if (current_field) wrap_up_field(); if (current_tab) wrap_up_tab(); // strip trailing spaces while (line != 0 && line->discardable()) { width_total -= line->width(); space_total -= line->nspaces(); node *tem = line; line = line->next; delete tem; } node *to_be_output = 0; hunits to_be_output_width; prev_line_interrupted = 0; if (dummy) space_newline(); else if (interrupted) { interrupted = 0; // see environment::final_break prev_line_interrupted = exit_started ? 2 : 1; } else if (center_lines > 0) { --center_lines; hunits x = target_text_length - width_total; if (x > H0) saved_indent += x/2; to_be_output = line; to_be_output_width = width_total; line = 0; } else if (right_justify_lines > 0) { --right_justify_lines; hunits x = target_text_length - width_total; if (x > H0) saved_indent += x; to_be_output = line; to_be_output_width = width_total; line = 0; } else if (fill) space_newline(); else { to_be_output = line; to_be_output_width = width_total; line = 0; } input_line_start = line == 0 ? H0 : width_total; if (to_be_output) { output_line(to_be_output, to_be_output_width); hyphen_line_count = 0; } if (input_trap_count > 0) { if (--input_trap_count == 0) spring_trap(input_trap); }}void environment::output_line(node *n, hunits width){ prev_text_length = width; if (margin_character_flags) { hunits d = line_length + margin_character_distance - saved_indent - width; if (d > 0) { n = new hmotion_node(d, n); width += d; } margin_character_flags &= ~MARGIN_CHARACTER_NEXT; node *tem; if (!margin_character_flags) { tem = margin_character_node; margin_character_node = 0; } else tem = margin_character_node->copy(); tem->next = n; n = tem; width += tem->width(); } node *nn = 0; while (n != 0) { node *tem = n->next; n->next = nn; nn = n; n = tem; } if (!saved_indent.is_zero()) nn = new hmotion_node(saved_indent, nn); width += saved_indent; if (no_number_count > 0) --no_number_count; else if (numbering_nodes) { hunits w = (line_number_digit_width *(3+line_number_indent+number_text_separation)); if (next_line_number % line_number_multiple != 0) nn = new hmotion_node(w, nn); else { hunits x = w; nn = new hmotion_node(number_text_separation*line_number_digit_width, nn); x -= number_text_separation*line_number_digit_width; char buf[30]; sprintf(buf, "%3d", next_line_number); for (char *p = strchr(buf, '\0') - 1; p >= buf && *p != ' '; --p) { node *gn = numbering_nodes; for (int count = *p - '0'; count > 0; count--) gn = gn->next; gn = gn->copy(); x -= gn->width(); gn->next = nn; nn = gn; } nn = new hmotion_node(x, nn); } width += w; ++next_line_number; } output(nn, !fill, vertical_spacing, line_spacing, width);}void environment::start_line(){ assert(line == 0); discarding = 0; line = new line_start_node; if (have_temporary_indent) { saved_indent = temporary_indent; have_temporary_indent = 0; } else saved_indent = indent; target_text_length = line_length - saved_indent; width_total = H0; space_total = 0;}hunits environment::get_hyphenation_space(){ return hyphenation_space;}void hyphenation_space_request(){ hunits n; if (get_hunits(&n, 'm')) { if (n < H0) { warning(WARN_RANGE, "hyphenation space cannot be negative"); n = H0; } curenv->hyphenation_space = n; } skip_line();}hunits environment::get_hyphenation_margin(){ return hyphenation_margin;}void hyphenation_margin_request(){ hunits n; if (get_hunits(&n, 'm')) { if (n < H0) { warning(WARN_RANGE, "hyphenation margin cannot be negative"); n = H0; } curenv->hyphenation_margin = n; } skip_line();}breakpoint *environment::choose_breakpoint(){ hunits x = width_total; int s = space_total; node *n = line; breakpoint *best_bp = 0; // the best breakpoint so far int best_bp_fits = 0; while (n != 0) { x -= n->width(); s -= n->nspaces(); breakpoint *bp = n->get_breakpoints(x, s); while (bp != 0) { if (bp->width <= target_text_length) { if (!bp->hyphenated) { breakpoint *tem = bp->next; bp->next = 0; while (tem != 0) { breakpoint *tem1 = tem; tem = tem->next; delete tem1; } if (best_bp_fits // Decide whether to use the hyphenated breakpoint. && (hyphen_line_max < 0 // Only choose the hyphenated breakpoint if it would not // exceed the maximum number of consecutive hyphenated // lines. || hyphen_line_count + 1 <= hyphen_line_max) && !(adjust_mode == ADJUST_BOTH // Don't choose the hyphenated breakpoint if the line // can be justified by adding no more than // hyphenation_space to any word space. ? (bp->nspaces > 0 && (((target_text_length - bp->width + (bp->nspaces - 1)*hresolution)/bp->nspaces) <= hyphenation_space)) // Don't choose the hyphenated breakpoint if the line // is no more than hyphenation_margin short. : target_text_length - bp->width <= hyphenation_margin)) { delete bp; return best_bp; } if (best_bp) delete best_bp; return bp; } else { if ((adjust_mode == ADJUST_BOTH ? hyphenation_space == H0 : hyphenation_margin == H0) && (hyphen_line_max < 0 || hyphen_line_count + 1 <= hyphen_line_max)) { // No need to consider a non-hyphenated breakpoint. if (best_bp) delete best_bp; return bp; } // It fits but it's hyphenated. if (!best_bp_fits) { if (best_bp) delete best_bp; best_bp = bp; bp = bp->next; best_bp_fits = 1; } else { breakpoint *tem = bp; bp = bp->next; delete tem; } } } else { if (best_bp) delete best_bp; best_bp = bp; bp = bp->next; } } n = n->next; } if (best_bp) { if (!best_bp_fits) warning(WARN_BREAK, "can't break line"); return best_bp; } return 0;}void environment::hyphenate_line(){ if (line == 0) return; hyphenation_type prev_type = line->get_hyphenation_type(); for (node **startp = &line->next; *startp != 0; startp = &(*startp)->next) { hyphenation_type this_type = (*startp)->get_hyphenation_type(); if (prev_type == HYPHEN_BOUNDARY && this_type == HYPHEN_MIDDLE) break; prev_type = this_type; } if (*startp == 0) return; node *tem = *startp; int i = 0; do { ++i; tem = tem->next; } while (tem != 0 && tem->get_hyphenation_type() == HYPHEN_MIDDLE); int inhibit = (tem != 0 && tem->get_hyphenation_type() == HYPHEN_INHIBIT); node *end = tem; hyphen_list *sl = 0; tem = *startp; node *forward = 0; while (tem != end) { sl = tem->get_hyphen_list(sl); node *tem1 = tem; tem = tem->next; tem1->next = forward; forward = tem1; } if (!inhibit) { // this is for characters like hyphen and emdash int prev_code = 0; for (hyphen_list *h = sl; h; h = h->next) { h->breakable = (prev_code != 0 && h->next != 0 && h->next->hyphenation_code != 0); prev_code = h->hyphenation_code; } } if (hyphenation_flags != 0 && !inhibit // this may not be right if we have extra space on this line && !((hyphenation_flags & HYPHEN_LAST_LINE) && curdiv->distance_to_next_trap() <= line_spacing*vertical_spacing) && i >= 4) hyphenate(sl, hyphenation_flags); while (forward != 0) { node *tem1 = forward; forward = forward->next; tem1->next = 0; tem = tem1->add_self(tem, &sl); } *startp = tem;}static node *node_list_reverse(node *n){ node *res = 0; while (n) { node *tem = n; n = n->next; tem->next = res; res = tem; } return res;}static void distribute_space(node *n, int nspaces, hunits desired_space, int force_reverse = 0){ static int reverse = 0; if (force_reverse || reverse) n = node_list_reverse(n); for (node *tem = n; tem; tem = tem->next) tem->spread_space(&nspaces, &desired_space); if (force_reverse || reverse) (void)node_list_reverse(n); if (!force_reverse) reverse = !reverse; assert(desired_space.is_zero() && nspaces == 0);}void environment::possibly_break_line(int forced){ if (!fill || current_tab || current_field || dummy) return; while (line != 0 && (forced || width_total > target_text_length)) { hyphenate_line(); breakpoint *bp = choose_breakpoint(); if (bp == 0) // we'll find one eventually return; node *pre, *post; node **ndp = &line; while (*ndp != bp->nd) ndp = &(*ndp)->next; bp->nd->split(bp->index, &pre, &post); *ndp = post; hunits extra_space_width = H0; switch(adjust_mode) { case ADJUST_BOTH: if (bp->nspaces != 0) extra_space_width = target_text_length - bp->width; break; case ADJUST_CENTER: saved_indent += (target_text_length - bp->width)/2; break; case ADJUST_RIGHT: saved_indent += target_text_length - bp->width; break; } distribute_space(pre, bp->nspaces, extra_space_width); hunits output_width = bp->width + extra_space_width; input_line_start -= output_width; if (bp->hyphenated) hyphen_line_count++; else hyphen_line_count = 0; delete bp; space_total = 0; width_total = 0; node *first_non_discardable = 0; for (node *tem = line; tem != 0; tem = tem->next) if (!tem->discardable()) first_non_discardable = tem; node *to_be_discarded; if (first_non_discardable) { to_be_discarded = first_non_discardable->next; first_non_discardable->next = 0; for (tem = line; tem != 0; tem = tem->next) { width_total += tem->width(); space_total += tem->nspaces(); } discarding = 0; } else { discarding = 1; to_be_discarded = line; line = 0; } // Do output_line() here so that line will be 0 iff the // the environment will be empty. output_line(pre, output_width); while (to_be_discarded != 0) { tem = to_be_discarded; to_be_discarded = to_be_discarded->next; input_line_start -= tem->width(); delete tem; } if (line != 0) { if (have_temporary_indent) { saved_indent = temporary_indent; have_temporary_indent = 0; } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -