📄 wordwrap.c
字号:
/* * This module contains the word wrap and format paragraph functions. The * right_justify( ) function is based on the spread function in _Software * Tools_ by Brian Kernighan and P J Plauger. My version of the spread * function handles lines with extra blanks in the text, e.g. two blanks * after periods. All of the other word processing routines are original * and written by me, Frank, and are not guaranteed to work as designed. * * See: * * Brian W. Kernighan and P. J. Plauger, _Software Tools_, Addison- * Wesly, Reading, Mass., 1976, Section 7.7, "Right Margin Justification", * pp 239-242. ISBN 0-201-03669-X. * * Note: right margin justification was added in TDE 2.2. * * New editor name: TDE, the Thomson-Davis Editor. * Author: Frank Davis * Date: June 5, 1991, version 1.0 * Date: July 29, 1991, version 1.1 * Date: October 5, 1991, version 1.2 * Date: January 20, 1992, version 1.3 * Date: February 17, 1992, version 1.4 * Date: April 1, 1992, version 1.5 * Date: June 5, 1992, version 2.0 * Date: October 31, 1992, version 2.1 * Date: April 1, 1993, version 2.2 * Date: June 5, 1993, version 3.0 * Date: August 29, 1993, version 3.1 * Date: June 5, 1994, version 4.0 * Date: December 5, 1998, version 5.0 (jmh) * * This code is released into the public domain, Frank Davis. * You may distribute it freely. */#include "tdestr.h" /* global variables definitions */#include "common.h" /* external global variable declarations */#include "define.h"#include "tdefunc.h"/* * Name: find_left_margin * Purpose: find left margin depending on word wrap mode * Date: June 5, 1992 * Passed: ll: node pointer to current line * wrap_mode: current word wrap mode * tabs: are tabs expanded? * tab_size: size of tabs * Notes: the algorithm used to figure the indent column was yanked out * of the insert_newline( ) function and was made into a more * general algorithm for figuring the left margin irregardless * of word wrap or indent mode. when in the DYNAMIC_WRAP mode, * the user don't have to keep changing the left margin when * special indentation is needed. */int find_left_margin( line_list_ptr ll, int wrap_mode, int tabs, int tab_size ){register int lm;int len;text_ptr source; if (wrap_mode == FIXED_WRAP) { /* * for FIXED_WRAP mode, the left and paragraph margins are determined * from the master mode structure. */ if (g_status.copied) { source = g_status.line_buff; len = g_status.line_buff_len; } else { if (ll->prev->prev != NULL) { source = ll->prev->line; len = ll->prev->len; } else { source = NULL; len = 0; } } if (source == NULL) lm = mode.parg_margin; else if (find_end( source, len, tabs, tab_size ) == 0) lm = mode.parg_margin; else lm = mode.left_margin; } else { /* * for Indent and DYNAMIC_WRAP modes, the left margin is determined * from the first non blank line above the cursor. */ if (g_status.copied == TRUE) { source = g_status.line_buff; len = g_status.line_buff_len; } else { source = ll->line; len = ll->len; } while (is_line_blank( source, len, tabs ) && ll->prev != NULL) { ll = ll->prev; source = ll->line; len = ll->len; } lm = first_non_blank( source, len, tabs, tab_size ); } return( lm );}/* * Name: word_wrap * Purpose: make sure lines don't get longer than right margin * Date: November 27, 1991 * Passed: window: pointer to current window * Notes: rcol, lm, rm, pm all start counting at zero. * len (line length) starts counting at 1. * * when we compare margins and line lengths, we either have to * add one to the margins or subtract one from the len. I add * one to the margins. */void word_wrap( TDE_WIN *window ){int c; /* character the user just entered. */register int len; /* length of current line */int i; /* padding spaces required */line_list_ptr p; /* line above wrapped line */int rcol;int lm;int rm;int side;register TDE_WIN *win; /* put window pointer in a register */int tabs;int tab_size; win = window; tabs = win->file_info->inflate_tabs; tab_size = win->file_info->ptab_size; /* * set up a few local variables. */ c = (int)g_status.key_pressed; rcol = win->rcol; copy_line( win->ll, win, TRUE ); /* * always start the right margin justification on the right side * at the beginning of paragraphs. then, alternate with left margin. */ side = 1; p = win->ll->prev; while (p->prev != NULL && !is_line_blank( p->line, p->len, tabs )) { ++side; p = p->prev; } side = (side & 1) ? RIGHT : LEFT; /* * when we wrap, we need know where the left margin is. * let's look at the line above to see if this is the first line * in a paragraph. */ p = win->ll->prev; lm = find_left_margin( win->ll, mode.word_wrap, tabs, tab_size ); rm = mode.right_margin; /* * there two ways that words are pushed onto next line. * 1. if the word being typed goes over the right margin * 2. typing a word in the middle of the line pushes words at end of * line to next line * * if the user enters spaces past the right margin then we don't * word wrap spaces. */ len = g_status.line_buff_len; if (rcol > rm+1 && c != ' ') { /* * if this is the first line in a paragraph then set left margin * to paragraph margin. */ if ((p->prev == NULL || is_line_blank( p->line, p->len, tabs )) && mode.word_wrap == FIXED_WRAP && first_non_blank( g_status.line_buff, g_status.line_buff_len, tabs, tab_size ) > rm) lm = mode.parg_margin; /* * simple word wrap. the cursor goes past the right margin. * find the beginning of the word and put it on a new line. * * Special case - if the word begins at the left margin then * don't wrap it. */ for (i=rcol-1; i > lm && g_status.line_buff[i] != ' '; ) i--; if (i > lm) { i++; win->rcol = i; g_status.command = WordWrap; insert_newline( win ); if (mode.right_justify == TRUE) justify_right_margin( win, win->ll->prev, mode.word_wrap == FIXED_WRAP ? find_left_margin( win->ll->prev, mode.word_wrap, tabs, tab_size ) : lm, rm, side ); /* * find out where to place the cursor on the new line. */ win->rcol += rcol - i; check_virtual_col( win, win->rcol, win->rcol ); /* * we just wrapped the word at the eol. now, let's see if * we can combine it with the line below. since just added * a line, set new_line to false - don't add another line. */ len = find_end( win->ll->line, win->ll->len, tabs, tab_size ); if (len < rm+1) combine_wrap_spill( win, len, lm, rm, side, FALSE ); } } else if (len > rm+1) { /* * this is the second word wrap case. we are pushing words onto * next line. we need to know what character is in the right margin. * * 1) if the character is not a space, then we need to search backwards * to find the start of the word that is on the right margin. * 2) if the character is a space, then we need to search forward to * find the word that is over the right margin. */ /* * don't wrap spaces past right margin */ if (c == ' ' && rcol > rm) { for (i=rcol; i<len && g_status.line_buff[i] == ' ';) i++; /* * if i == len then all that's left on line is blanks - don't wrap. */ if (i < len) combine_wrap_spill( win, i, lm, rm, side, TRUE ); } else if (g_status.line_buff[rm+1] != ' ') { /* * search backwards for the word to put on next line. */ for (i=rm+1; i > lm && g_status.line_buff[i] != ' '; ) i--; /* * if we search all the way back to left margin then test for * a special case - see the matching else for more info. */ if (i > lm) { i++; /* * if i > rcol then cursor stays on same line. */ if (i > rcol) { combine_wrap_spill( win, i, lm, rm, side, TRUE ); /* * split the line at or behind the cursor. almost the * same as when the cursor goes over the right margin. */ } else if (i <= rcol) { win->rcol = i; g_status.command = WordWrap; insert_newline( win ); if (mode.right_justify == TRUE) justify_right_margin( win, win->ll->prev, mode.word_wrap == FIXED_WRAP ? find_left_margin( win->ll->prev, mode.word_wrap, tabs, tab_size ) : lm, rm, side ); win->rcol = lm + rcol - i; check_virtual_col( win, win->rcol, win->rcol ); len = find_end( win->ll->line, win->ll->len, tabs, tab_size ); if (len < rm+1) combine_wrap_spill( win, len, lm, rm, side, FALSE ); } } /* * if the user changed margins or for some reason there's a long * text line, let's see if there are any words past the right * margin. if we get to this else, we know the current word * begins at least at the left margin. * * now search forwards for a break */ } else { /* * go to the right margin and see if there are any words past * right margin. */ for (i=rm+1; i<len && g_status.line_buff[i] == ' '; ) i++; /* * we either found a space or the eol. test for eol. * if i == len then this is one big word - don't wrap it. */ if (i != len) combine_wrap_spill( win, i, lm, rm, side, TRUE ); } }}/* * Name: format_paragraph * Purpose: format paragraph using left, right, and paragraph margins. * Date: November 27, 1991 * Passed: window: pointer to current window * * jmh 010624: due to my re-working of adjust_windows_cursor(), * FormatParagraph needs to remember rline. * jmh 021012: keep the current position. */int format_paragraph( TDE_WIN *window ){register int len; /* length of current line */int first_line; /* boolean, first line formatted? */int spaces; /* no. of spaces to add */line_list_ptr p; /* scratch pointers */line_list_ptr pp;text_ptr source; /* scratch line buffer pointers */text_ptr dest;int rcol; /* scratch cols and margins */int lm;int rm;int pm;int margin;int eop; /* boolean, (e)nd (o)f (p)aragraph? */int old_ww; /* save state of word wrap flag */long rline;TDE_WIN w, u; /* scratch windows */int tabs;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -