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., 51 Franklin Street, Fifth Floor, Boston, MA
22 * \brief Source: word-processor mode for the editor: does dynamic paragraph formatting
31 #include <sys/types.h>
40 #include "lib/global.h"
42 #include "src/setup.h" /* option_tab_spacing */
44 #include "edit-impl.h"
45 #include "edit-widget.h"
47 /*** global variables ****************************************************************************/
49 /*** file scope macro definitions ****************************************************************/
51 #define tab_width option_tab_spacing
53 #define NO_FORMAT_CHARS_START "-+*\\,.;:&>"
54 #define FONT_MEAN_WIDTH 1
56 /*** file scope type declarations ****************************************************************/
58 /*** file scope variables ************************************************************************/
60 /*** file scope functions ************************************************************************/
61 /* --------------------------------------------------------------------------------------------- */
64 line_start (WEdit
* edit
, long line
)
72 p
= edit_move_backward (edit
, p
, l
- line
);
74 p
= edit_move_forward (edit
, p
, line
- l
, 0);
76 p
= edit_bol (edit
, p
);
77 while (strchr ("\t ", edit_get_byte (edit
, p
)))
82 /* --------------------------------------------------------------------------------------------- */
85 bad_line_start (WEdit
* edit
, long p
)
88 c
= edit_get_byte (edit
, p
);
90 { /* `...' is acceptable */
91 if (edit_get_byte (edit
, p
+ 1) == '.')
92 if (edit_get_byte (edit
, p
+ 2) == '.')
98 if (edit_get_byte (edit
, p
+ 1) == '-')
99 if (edit_get_byte (edit
, p
+ 2) == '-')
100 return 0; /* `---' is acceptable */
103 if (strchr (NO_FORMAT_CHARS_START
, c
))
108 /* --------------------------------------------------------------------------------------------- */
110 * Find the start of the current paragraph for the purpose of formatting.
111 * Return position in the file.
115 begin_paragraph (WEdit
* edit
, int force
)
118 for (i
= edit
->curs_line
- 1; i
>= 0; i
--)
120 if (line_is_blank (edit
, i
))
127 if (bad_line_start (edit
, line_start (edit
, i
)))
134 return edit_move_backward (edit
, edit_bol (edit
, edit
->curs1
), edit
->curs_line
- i
);
137 /* --------------------------------------------------------------------------------------------- */
139 * Find the end of the current paragraph for the purpose of formatting.
140 * Return position in the file.
144 end_paragraph (WEdit
* edit
, int force
)
147 for (i
= edit
->curs_line
+ 1; i
<= edit
->total_lines
; i
++)
149 if (line_is_blank (edit
, i
))
155 if (bad_line_start (edit
, line_start (edit
, i
)))
161 return edit_eol (edit
,
162 edit_move_forward (edit
, edit_bol (edit
, edit
->curs1
),
163 i
- edit
->curs_line
, 0));
166 /* --------------------------------------------------------------------------------------------- */
168 static unsigned char *
169 get_paragraph (WEdit
* edit
, long p
, long q
, int indent
, int *size
)
171 unsigned char *s
, *t
;
173 t
= g_try_malloc ((q
- p
) + 2 * (q
- p
) / option_word_wrap_line_length
+ 10);
175 t
= g_try_malloc (2 * (q
- p
) + 100);
179 for (s
= t
; p
< q
; p
++, s
++)
182 if (edit_get_byte (edit
, p
- 1) == '\n')
183 while (strchr ("\t ", edit_get_byte (edit
, p
)))
185 *s
= edit_get_byte (edit
, p
);
187 *size
= (unsigned long) s
- (unsigned long) t
;
192 /* --------------------------------------------------------------------------------------------- */
195 strip_newlines (unsigned char *t
, int size
)
197 unsigned char *p
= t
;
206 /* --------------------------------------------------------------------------------------------- */
208 This function calculates the number of chars in a line specified to length l in pixels
214 return x
+= tab_width
- x
% tab_width
;
217 /* --------------------------------------------------------------------------------------------- */
220 line_pixel_length (unsigned char *t
, long b
, int l
)
222 int x
= 0, c
, xn
= 0;
231 xn
= next_tab_pos (x
);
245 /* --------------------------------------------------------------------------------------------- */
248 next_word_start (unsigned char *t
, int q
, int size
)
253 for (i
= q
; i
< size
; i
++)
272 /* --------------------------------------------------------------------------------------------- */
273 /** find the start of a word */
276 word_start (unsigned char *t
, int q
, int size
)
279 if (t
[q
] == ' ' || t
[q
] == '\t')
280 return next_word_start (t
, q
, size
);
289 if (c
== ' ' || c
== '\t')
295 /* --------------------------------------------------------------------------------------------- */
296 /** replaces ' ' with '\n' to properly format a paragraph */
299 format_this (unsigned char *t
, int size
, int indent
)
302 strip_newlines (t
, size
);
303 ww
= option_word_wrap_line_length
* FONT_MEAN_WIDTH
- indent
;
304 if (ww
< FONT_MEAN_WIDTH
* 2)
305 ww
= FONT_MEAN_WIDTH
* 2;
309 q
= line_pixel_length (t
, q
, ww
);
314 p
= word_start (t
, q
, size
);
316 q
= next_word_start (t
, q
, size
); /* Return the end of the word if the beginning
317 of the word is at the beginning of a line
318 (i.e. a very long word) */
321 if (q
== -1) /* end of paragraph */
328 /* --------------------------------------------------------------------------------------------- */
331 replace_at (WEdit
* edit
, long q
, int c
)
333 edit_cursor_move (edit
, q
- edit
->curs1
);
334 edit_delete (edit
, 1);
335 edit_insert_ahead (edit
, c
);
338 /* --------------------------------------------------------------------------------------------- */
339 /** replaces a block of text */
342 put_paragraph (WEdit
* edit
, unsigned char *t
, long p
, int indent
, int size
)
346 cursor
= edit
->curs1
;
348 while (strchr ("\t ", edit_get_byte (edit
, p
)))
350 for (i
= 0; i
< size
; i
++, p
++)
354 if (t
[i
- 1] == '\n' && c
== '\n')
356 while (strchr ("\t ", edit_get_byte (edit
, p
)))
359 else if (t
[i
- 1] == '\n')
362 edit_cursor_move (edit
, p
- edit
->curs1
);
364 edit_insert_indent (edit
, indent
);
366 cursor
+= edit
->curs1
- p
;
371 edit_cursor_move (edit
, p
- edit
->curs1
);
372 while (strchr ("\t ", edit_get_byte (edit
, p
)))
374 edit_delete (edit
, 1);
375 if (cursor
> edit
->curs1
)
381 c
= edit_get_byte (edit
, p
);
383 replace_at (edit
, p
, t
[i
]);
385 edit_cursor_move (edit
, cursor
- edit
->curs1
); /* restore cursor position */
388 /* --------------------------------------------------------------------------------------------- */
391 test_indent (WEdit
* edit
, long p
, long q
)
394 indent
= edit_indent_width (edit
, p
++);
398 if (edit_get_byte (edit
, p
- 1) == '\n')
399 if (indent
!= edit_indent_width (edit
, p
))
404 /* --------------------------------------------------------------------------------------------- */
405 /*** public functions ****************************************************************************/
406 /* --------------------------------------------------------------------------------------------- */
409 format_paragraph (WEdit
* edit
, int force
)
415 if (option_word_wrap_line_length
< 2)
417 if (line_is_blank (edit
, edit
->curs_line
))
419 p
= begin_paragraph (edit
, force
);
420 q
= end_paragraph (edit
, force
);
421 indent
= test_indent (edit
, p
, q
);
422 t
= get_paragraph (edit
, p
, q
, indent
, &size
);
428 if (strchr (NO_FORMAT_CHARS_START
, *t
))
433 for (i
= 0; i
< size
- 1; i
++)
437 if (strchr (NO_FORMAT_CHARS_START
"\t ", t
[i
+ 1]))
445 format_this (t
, q
- p
, indent
);
446 put_paragraph (edit
, t
, p
, indent
, size
);
449 /* Scroll left as much as possible to show the formatted paragraph */
450 edit_scroll_left (edit
, -edit
->start_col
);
453 /* --------------------------------------------------------------------------------------------- */