2 Word-processor mode for the editor: does dynamic
6 The Free Software Foundation, Inc.
8 Copyright (C) 1996 Paul Sheer
13 This file is part of the Midnight Commander.
15 The Midnight Commander is free software: you can redistribute it
16 and/or modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation, either version 3 of the License,
18 or (at your option) any later version.
20 The Midnight Commander is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 * \brief Source: word-processor mode for the editor: does dynamic paragraph formatting
39 #include <sys/types.h>
48 #include "lib/global.h"
50 #include "src/setup.h" /* option_tab_spacing */
52 #include "edit-impl.h"
53 #include "editwidget.h"
55 /*** global variables ****************************************************************************/
57 /*** file scope macro definitions ****************************************************************/
59 #define tab_width option_tab_spacing
61 #define NO_FORMAT_CHARS_START "-+*\\,.;:&>"
62 #define FONT_MEAN_WIDTH 1
64 /*** file scope type declarations ****************************************************************/
66 /*** file scope variables ************************************************************************/
68 /*** file scope functions ************************************************************************/
69 /* --------------------------------------------------------------------------------------------- */
72 line_start (WEdit
* edit
, long line
)
81 p
= edit_move_backward (edit
, p
, l
- line
);
83 p
= edit_move_forward (edit
, p
, line
- l
, 0);
85 p
= edit_bol (edit
, p
);
86 while (strchr ("\t ", edit_get_byte (edit
, p
)))
91 /* --------------------------------------------------------------------------------------------- */
94 bad_line_start (WEdit
* edit
, off_t p
)
97 c
= edit_get_byte (edit
, p
);
99 { /* `...' is acceptable */
100 if (edit_get_byte (edit
, p
+ 1) == '.')
101 if (edit_get_byte (edit
, p
+ 2) == '.')
107 if (edit_get_byte (edit
, p
+ 1) == '-')
108 if (edit_get_byte (edit
, p
+ 2) == '-')
109 return 0; /* `---' is acceptable */
112 if (strchr (NO_FORMAT_CHARS_START
, c
))
117 /* --------------------------------------------------------------------------------------------- */
119 * Find the start of the current paragraph for the purpose of formatting.
120 * Return position in the file.
124 begin_paragraph (WEdit
* edit
, int force
)
127 for (i
= edit
->curs_line
- 1; i
>= 0; i
--)
129 if (edit_line_is_blank (edit
, i
))
136 if (bad_line_start (edit
, line_start (edit
, i
)))
143 return edit_move_backward (edit
, edit_bol (edit
, edit
->curs1
), edit
->curs_line
- i
);
146 /* --------------------------------------------------------------------------------------------- */
148 * Find the end of the current paragraph for the purpose of formatting.
149 * Return position in the file.
153 end_paragraph (WEdit
* edit
, int force
)
156 for (i
= edit
->curs_line
+ 1; i
<= edit
->total_lines
; i
++)
158 if (edit_line_is_blank (edit
, i
))
164 if (bad_line_start (edit
, line_start (edit
, i
)))
170 return edit_eol (edit
,
171 edit_move_forward (edit
, edit_bol (edit
, edit
->curs1
),
172 i
- edit
->curs_line
, 0));
175 /* --------------------------------------------------------------------------------------------- */
177 static unsigned char *
178 get_paragraph (WEdit
* edit
, off_t p
, off_t q
, int indent
, int *size
)
180 unsigned char *s
, *t
;
182 t
= g_try_malloc ((q
- p
) + 2 * (q
- p
) / option_word_wrap_line_length
+ 10);
184 t
= g_try_malloc (2 * (q
- p
) + 100);
188 for (s
= t
; p
< q
; p
++, s
++)
191 if (edit_get_byte (edit
, p
- 1) == '\n')
192 while (strchr ("\t ", edit_get_byte (edit
, p
)))
194 *s
= edit_get_byte (edit
, p
);
196 *size
= (unsigned long) (s
- t
);
197 /* FIXME: all variables related to 'size' should be fixed */
202 /* --------------------------------------------------------------------------------------------- */
205 strip_newlines (unsigned char *t
, int size
)
207 unsigned char *p
= t
;
216 /* --------------------------------------------------------------------------------------------- */
218 This function calculates the number of chars in a line specified to length l in pixels
224 return x
+= tab_width
- x
% tab_width
;
227 /* --------------------------------------------------------------------------------------------- */
230 line_pixel_length (unsigned char *t
, long b
, int l
)
232 int x
= 0, c
, xn
= 0;
242 xn
= next_tab_pos (x
);
256 /* --------------------------------------------------------------------------------------------- */
259 next_word_start (unsigned char *t
, int q
, int size
)
264 for (i
= q
; i
< size
; i
++)
283 /* --------------------------------------------------------------------------------------------- */
284 /** find the start of a word */
287 word_start (unsigned char *t
, int q
, int size
)
291 if (t
[q
] == ' ' || t
[q
] == '\t')
292 return next_word_start (t
, q
, size
);
303 if (c
== ' ' || c
== '\t')
309 /* --------------------------------------------------------------------------------------------- */
310 /** replaces ' ' with '\n' to properly format a paragraph */
313 format_this (unsigned char *t
, int size
, int indent
)
317 strip_newlines (t
, size
);
318 ww
= option_word_wrap_line_length
* FONT_MEAN_WIDTH
- indent
;
319 if (ww
< FONT_MEAN_WIDTH
* 2)
320 ww
= FONT_MEAN_WIDTH
* 2;
325 q
= line_pixel_length (t
, q
, ww
);
330 p
= word_start (t
, q
, size
);
332 q
= next_word_start (t
, q
, size
); /* Return the end of the word if the beginning
333 of the word is at the beginning of a line
334 (i.e. a very long word) */
337 if (q
== -1) /* end of paragraph */
344 /* --------------------------------------------------------------------------------------------- */
347 replace_at (WEdit
* edit
, long q
, int c
)
349 edit_cursor_move (edit
, q
- edit
->curs1
);
350 edit_delete (edit
, TRUE
);
351 edit_insert_ahead (edit
, c
);
354 /* --------------------------------------------------------------------------------------------- */
355 /** replaces a block of text */
358 put_paragraph (WEdit
* edit
, unsigned char *t
, off_t p
, int indent
, int size
)
363 cursor
= edit
->curs1
;
365 while (strchr ("\t ", edit_get_byte (edit
, p
)))
367 for (i
= 0; i
< size
; i
++, p
++)
371 if (t
[i
- 1] == '\n' && c
== '\n')
373 while (strchr ("\t ", edit_get_byte (edit
, p
)))
376 else if (t
[i
- 1] == '\n')
379 edit_cursor_move (edit
, p
- edit
->curs1
);
381 edit_insert_indent (edit
, indent
);
383 cursor
+= edit
->curs1
- p
;
388 edit_cursor_move (edit
, p
- edit
->curs1
);
389 while (strchr ("\t ", edit_get_byte (edit
, p
)))
391 edit_delete (edit
, TRUE
);
392 if (cursor
> edit
->curs1
)
398 c
= edit_get_byte (edit
, p
);
400 replace_at (edit
, p
, t
[i
]);
402 edit_cursor_move (edit
, cursor
- edit
->curs1
); /* restore cursor position */
405 /* --------------------------------------------------------------------------------------------- */
408 test_indent (const WEdit
* edit
, off_t p
, off_t q
)
412 indent
= edit_indent_width (edit
, p
++);
417 if (edit_get_byte (edit
, p
- 1) == '\n')
418 if (indent
!= edit_indent_width (edit
, p
))
423 /* --------------------------------------------------------------------------------------------- */
424 /*** public functions ****************************************************************************/
425 /* --------------------------------------------------------------------------------------------- */
428 format_paragraph (WEdit
* edit
, int force
)
434 if (option_word_wrap_line_length
< 2)
436 if (edit_line_is_blank (edit
, edit
->curs_line
))
438 p
= begin_paragraph (edit
, force
);
439 q
= end_paragraph (edit
, force
);
440 indent
= test_indent (edit
, p
, q
);
441 t
= get_paragraph (edit
, p
, q
, indent
, &size
);
447 if (strchr (NO_FORMAT_CHARS_START
, *t
))
452 for (i
= 0; i
< size
- 1; i
++)
456 if (strchr (NO_FORMAT_CHARS_START
"\t ", t
[i
+ 1]))
464 format_this (t
, q
- p
, indent
);
465 put_paragraph (edit
, t
, p
, indent
, size
);
468 /* Scroll left as much as possible to show the formatted paragraph */
469 edit_scroll_left (edit
, -edit
->start_col
);
472 /* --------------------------------------------------------------------------------------------- */