📄 wordproc.c
字号:
/* wordproc.c - word-processor mode for the editor: does dynamic paragraph formatting. Copyright (C) 1996-2000 Paul Sheer This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */#include <config.h>#include "edit.h"#if defined (HAVE_MAD) && ! defined (MIDNIGHT) && ! defined (GTK)#include "mad.h"#endif#ifdef MIDNIGHT#define tab_width option_tab_spacing#endifint line_is_blank (WEdit * edit, long line);#define NO_FORMAT_CHARS_START "-+*\\,.;:&>"static long line_start (WEdit * edit, long line){ static long p = -1, l = 0; int c; if (p == -1 || abs (l - line) > abs (edit->curs_line - line)) { l = edit->curs_line; p = edit->curs1; } if (line < l) p = edit_move_backward (edit, p, l - line); else if (line > l) p = edit_move_forward (edit, p, line - l, 0); l = line; p = edit_bol (edit, p); while (strchr ("\t ", c = edit_get_byte (edit, p))) p++; return p;}static int bad_line_start (WEdit * edit, long p){ int c; c = edit_get_byte (edit, p); if (c == '.') { /* `...' is acceptable */ if (edit_get_byte (edit, p + 1) == '.') if (edit_get_byte (edit, p + 2) == '.') return 0; return 1; } if (c == '-') { if (edit_get_byte (edit, p + 1) == '-') if (edit_get_byte (edit, p + 2) == '-') return 0; /* `---' is acceptable */ return 1; } if (strchr (NO_FORMAT_CHARS_START, c)) return 1; return 0;}static long begin_paragraph (WEdit * edit, long p, int force){ int i; for (i = edit->curs_line - 1; i > 0; i--) { if (line_is_blank (edit, i)) { i++; break; } if (force) { if (bad_line_start (edit, line_start (edit, i))) { i++; break; } } } return edit_move_backward (edit, edit_bol (edit, edit->curs1), edit->curs_line - i);}static long end_paragraph (WEdit * edit, long p, int force){ int i; for (i = edit->curs_line + 1; i < edit->total_lines; i++) { if (line_is_blank (edit, i)) { i--; break; } if (force) if (bad_line_start (edit, line_start (edit, i))) { i--; break; } } return edit_eol (edit, edit_move_forward (edit, edit_bol (edit, edit->curs1), i - edit->curs_line, 0));}static unsigned char *get_paragraph (WEdit * edit, long p, long q, int indent, int *size){ unsigned char *s, *t;#if 0 t = malloc ((q - p) + 2 * (q - p) / option_word_wrap_line_length + 10);#else t = malloc (2 * (q - p) + 1024);#endif if (!t) return 0; for (s = t; p < q; p++, s++) { if (indent) if (edit_get_byte (edit, p - 1) == '\n') while (strchr ("\t ", edit_get_byte (edit, p))) p++; *s = edit_get_byte (edit, p); } *size = (unsigned long) s - (unsigned long) t; t[*size] = '\n'; return t;}static void strip_newlines (unsigned char *t, int size){ unsigned char *p = t; while (size--) { *p = *p == '\n' ? ' ' : *p; p++; }}#ifndef MIDNIGHTint edit_width_of_long_printable (int c);#endif/* This is a copy of the function int calc_text_pos (WEdit * edit, long b, long *q, int l) in propfont.c :( It calculates the number of chars in a line specified to length l in pixels */extern int tab_width;static inline int next_tab_pos (int x){ return x += tab_width - x % tab_width;}static int line_pixel_length (unsigned char *t, long b, int l){ int x = 0, c, xn = 0; for (;;) { c = t[b]; switch (c) { case '\n': return b; case '\t': xn = next_tab_pos (x); break; default:#ifdef MIDNIGHT xn = x + 1;#else xn = x + edit_width_of_long_printable (c);#endif break; } if (xn > l) break; x = xn; b++; } return b;}/* find the start of a word */static int next_word_start (unsigned char *t, int q, int size){ int i; for (i = q;; i++) { switch (t[i]) { case '\n': return -1; case '\t': case ' ': for (;; i++) { if (t[i] == '\n') return -1; if (t[i] != ' ' && t[i] != '\t') return i; } break; } }}/* find the start of a word */static int word_start (unsigned char *t, int q, int size){ int i = q; if (t[q] == ' ' || t[q] == '\t') return next_word_start (t, q, size); for (;;) { int c; if (!i) return -1; c = t[i - 1]; if (c == '\n') return -1; if (c == ' ' || c == '\t') return i; i--; }}/* replaces ' ' with '\n' to properly format a paragraph */static void format_this (unsigned char *t, int size, int indent){ int q = 0, ww; strip_newlines (t, size); ww = option_word_wrap_line_length * FONT_MEAN_WIDTH - indent; if (ww < FONT_MEAN_WIDTH * 2) ww = FONT_MEAN_WIDTH * 2; for (;;) { int p; q = line_pixel_length (t, q, ww); if (q > size) break; if (t[q] == '\n') break; p = word_start (t, q, size); if (p == -1) q = next_word_start (t, q, size); /* Return the end of the word if the beginning of the word is at the beginning of a line (i.e. a very long word) */ else q = p; if (q == -1) /* end of paragraph */ break; if (q) t[q - 1] = '\n'; }}static void replace_at (WEdit * edit, long q, int c){ edit_cursor_move (edit, q - edit->curs1); edit_delete (edit); edit_insert_ahead (edit, c);}void edit_insert_indent (WEdit * edit, int indent);/* replaces a block of text */static void put_paragraph (WEdit * edit, unsigned char *t, long p, long q, int indent, int size){ long cursor; int i, c = 0; cursor = edit->curs1; if (indent) while (strchr ("\t ", edit_get_byte (edit, p))) p++; for (i = 0; i < size; i++, p++) { if (i && indent) { if (t[i - 1] == '\n' && c == '\n') { while (strchr ("\t ", edit_get_byte (edit, p))) p++; } else if (t[i - 1] == '\n') { long curs; edit_cursor_move (edit, p - edit->curs1); curs = edit->curs1; edit_insert_indent (edit, indent); if (cursor >= curs) cursor += edit->curs1 - p; p = edit->curs1; } else if (c == '\n') { edit_cursor_move (edit, p - edit->curs1); while (strchr ("\t ", edit_get_byte (edit, p))) { edit_delete (edit); if (cursor > edit->curs1) cursor--; } p = edit->curs1; } } c = edit_get_byte (edit, p); if (c != t[i]) replace_at (edit, p, t[i]); } edit_cursor_move (edit, cursor - edit->curs1); /* restore cursor position */}int edit_indent_width (WEdit * edit, long p);static int test_indent (WEdit * edit, long p, long q){ int indent; indent = edit_indent_width (edit, p++); if (!indent) return 0; for (; p < q; p++) if (edit_get_byte (edit, p - 1) == '\n') if (indent != edit_indent_width (edit, p)) return 0; return indent;}static void new_behaviour_message (WEdit * edit){ char *filename; int fd; filename = catstrs (home_dir, PARMESS_FILE, 0); if ((fd = open (filename, O_RDONLY)) < 0) { edit_message_dialog (_(" Format Paragraph "), "\This message will not be displayed again\n\\n\The new \"format paragraph\" command will format\n\text inside the selected region if one is highlighted.\n\Otherwise it would try to find the bounds of the\n\current paragraph using heuristics."); fd = creat (filename, 0400); } close (fd);}void format_paragraph (WEdit * edit, int force){ long p, q; int size; unsigned char *t; int indent = 0; if (option_word_wrap_line_length < 2) return; if (force) new_behaviour_message (edit); if (force && !eval_marks (edit, &p, &q)) { p = edit_bol (edit, p); q = edit_eol (edit, q); } else { if (line_is_blank (edit, edit->curs_line)) return; p = begin_paragraph (edit, edit->curs1, force); q = end_paragraph (edit, edit->curs1, force); } CPushFont ("editor", 0); indent = test_indent (edit, p, q); t = get_paragraph (edit, p, q, indent, &size); if (!t) return; if (!force) { int i; if (strchr (NO_FORMAT_CHARS_START, *t)) { free (t); return; } for (i = 0; i < size - 1; i++) { if (t[i] == '\n') { if (strchr (NO_FORMAT_CHARS_START "\t ", t[i + 1])) { free (t); return; } } } } format_this (t, q - p, indent); put_paragraph (edit, t, p, q, indent, size); free (t); CPopFont ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -