1 /* wordproc.c - word-processor mode for the editor: does dynamic
3 Copyright (C) 1996 Paul Sheer
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 #if defined (HAVE_MAD) && ! defined (MIDNIGHT) && ! defined (GTK)
28 #define tab_width option_tab_spacing
31 int line_is_blank (WEdit
* edit
, long line
);
33 #define NO_FORMAT_CHARS_START "-+*\\,.;:&>"
35 static long line_start (WEdit
* edit
, long line
)
37 static long p
= -1, l
= 0;
39 if (p
== -1 || abs (l
- line
) > abs (edit
->curs_line
- line
)) {
44 p
= edit_move_backward (edit
, p
, l
- line
);
46 p
= edit_move_forward (edit
, p
, line
- l
, 0);
48 p
= edit_bol (edit
, p
);
49 while (strchr ("\t ", c
= edit_get_byte (edit
, p
)))
54 static int bad_line_start (WEdit
* edit
, long p
)
57 c
= edit_get_byte (edit
, p
);
58 if (c
== '.') { /* `...' is acceptable */
59 if (edit_get_byte (edit
, p
+ 1) == '.')
60 if (edit_get_byte (edit
, p
+ 2) == '.')
65 if (edit_get_byte (edit
, p
+ 1) == '-')
66 if (edit_get_byte (edit
, p
+ 2) == '-')
67 return 0; /* `---' is acceptable */
70 if (strchr (NO_FORMAT_CHARS_START
, c
))
75 static long begin_paragraph (WEdit
* edit
, long p
, int force
)
78 for (i
= edit
->curs_line
- 1; i
> 0; i
--) {
79 if (line_is_blank (edit
, i
)) {
84 if (bad_line_start (edit
, line_start (edit
, i
))) {
90 return edit_move_backward (edit
, edit_bol (edit
, edit
->curs1
), edit
->curs_line
- i
);
93 static long end_paragraph (WEdit
* edit
, long p
, int force
)
96 for (i
= edit
->curs_line
+ 1; i
< edit
->total_lines
; i
++) {
97 if (line_is_blank (edit
, i
)) {
102 if (bad_line_start (edit
, line_start (edit
, i
))) {
107 return edit_eol (edit
, edit_move_forward (edit
, edit_bol (edit
, edit
->curs1
), i
- edit
->curs_line
, 0));
110 static unsigned char *get_paragraph (WEdit
* edit
, long p
, long q
, int indent
, int *size
)
112 unsigned char *s
, *t
;
114 t
= malloc ((q
- p
) + 2 * (q
- p
) / option_word_wrap_line_length
+ 10);
116 t
= malloc (2 * (q
- p
) + 100);
120 for (s
= t
; p
< q
; p
++, s
++) {
122 if (edit_get_byte (edit
, p
- 1) == '\n')
123 while (strchr ("\t ", edit_get_byte (edit
, p
)))
125 *s
= edit_get_byte (edit
, p
);
127 *size
= (unsigned long) s
- (unsigned long) t
;
132 static void strip_newlines (unsigned char *t
, int size
)
134 unsigned char *p
= t
;
136 *p
= *p
== '\n' ? ' ' : *p
;
142 int edit_width_of_long_printable (int c
);
145 This is a copy of the function
146 int calc_text_pos (WEdit * edit, long b, long *q, int l)
148 It calculates the number of chars in a line specified to length l in pixels
150 extern int tab_width
;
151 static inline int next_tab_pos (int x
)
153 return x
+= tab_width
- x
% tab_width
;
155 static int line_pixel_length (unsigned char *t
, long b
, int l
)
157 int x
= 0, c
, xn
= 0;
164 xn
= next_tab_pos (x
);
170 xn
= x
+ edit_width_of_long_printable (c
);
182 /* find the start of a word */
183 static int next_word_start (unsigned char *t
, int q
, int size
)
195 if (t
[i
] != ' ' && t
[i
] != '\t')
203 /* find the start of a word */
204 static int word_start (unsigned char *t
, int q
, int size
)
207 if (t
[q
] == ' ' || t
[q
] == '\t')
208 return next_word_start (t
, q
, size
);
216 if (c
== ' ' || c
== '\t')
222 /* replaces ' ' with '\n' to properly format a paragraph */
223 static void format_this (unsigned char *t
, int size
, int indent
)
226 strip_newlines (t
, size
);
227 ww
= option_word_wrap_line_length
* FONT_MEAN_WIDTH
- indent
;
228 if (ww
< FONT_MEAN_WIDTH
* 2)
229 ww
= FONT_MEAN_WIDTH
* 2;
232 q
= line_pixel_length (t
, q
, ww
);
237 p
= word_start (t
, q
, size
);
239 q
= next_word_start (t
, q
, size
); /* Return the end of the word if the beginning
240 of the word is at the beginning of a line
241 (i.e. a very long word) */
244 if (q
== -1) /* end of paragraph */
251 static void replace_at (WEdit
* edit
, long q
, int c
)
253 edit_cursor_move (edit
, q
- edit
->curs1
);
255 edit_insert_ahead (edit
, c
);
258 void edit_insert_indent (WEdit
* edit
, int indent
);
260 /* replaces a block of text */
261 static void put_paragraph (WEdit
* edit
, unsigned char *t
, long p
, long q
, int indent
, int size
)
265 cursor
= edit
->curs1
;
267 while (strchr ("\t ", edit_get_byte (edit
, p
)))
269 for (i
= 0; i
< size
; i
++, p
++) {
271 if (t
[i
- 1] == '\n' && c
== '\n') {
272 while (strchr ("\t ", edit_get_byte (edit
, p
)))
274 } else if (t
[i
- 1] == '\n') {
276 edit_cursor_move (edit
, p
- edit
->curs1
);
278 edit_insert_indent (edit
, indent
);
280 cursor
+= edit
->curs1
- p
;
282 } else if (c
== '\n') {
283 edit_cursor_move (edit
, p
- edit
->curs1
);
284 while (strchr ("\t ", edit_get_byte (edit
, p
))) {
286 if (cursor
> edit
->curs1
)
292 c
= edit_get_byte (edit
, p
);
294 replace_at (edit
, p
, t
[i
]);
296 edit_cursor_move (edit
, cursor
- edit
->curs1
); /* restore cursor position */
299 int edit_indent_width (WEdit
* edit
, long p
);
301 static int test_indent (WEdit
* edit
, long p
, long q
)
304 indent
= edit_indent_width (edit
, p
++);
308 if (edit_get_byte (edit
, p
- 1) == '\n')
309 if (indent
!= edit_indent_width (edit
, p
))
314 void format_paragraph (WEdit
* edit
, int force
)
320 if (option_word_wrap_line_length
< 2)
322 if (line_is_blank (edit
, edit
->curs_line
))
324 p
= begin_paragraph (edit
, edit
->curs1
, force
);
325 q
= end_paragraph (edit
, edit
->curs1
, force
);
326 indent
= test_indent (edit
, p
, q
);
327 t
= get_paragraph (edit
, p
, q
, indent
, &size
);
332 if (strchr (NO_FORMAT_CHARS_START
, *t
)) {
336 for (i
= 0; i
< size
- 1; i
++) {
338 if (strchr (NO_FORMAT_CHARS_START
"\t ", t
[i
+ 1])) {
345 format_this (t
, q
- p
, indent
);
346 put_paragraph (edit
, t
, p
, q
, indent
, size
);