This source file includes following definitions.
- line_start
- bad_line_start
- begin_paragraph
- end_paragraph
- get_paragraph
- strip_newlines
- next_tab_pos
- line_pixel_length
- next_word_start
- word_start
- format_this
- replace_at
- edit_indent_width
- edit_insert_indent
- put_paragraph
- test_indent
- format_paragraph
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include <config.h>
38
39 #include <stdio.h>
40 #include <stdarg.h>
41 #include <sys/types.h>
42 #include <unistd.h>
43 #include <string.h>
44 #include <ctype.h>
45 #include <sys/stat.h>
46
47 #include <stdlib.h>
48
49 #include "lib/global.h"
50 #include "lib/util.h"
51
52 #include "edit-impl.h"
53 #include "editwidget.h"
54
55
56
57
58
59 #define FONT_MEAN_WIDTH 1
60
61
62
63
64
65
66
67
68
69
70
71 static off_t
72 line_start (const edit_buffer_t *buf, long line)
73 {
74 off_t p;
75 long l;
76
77 l = buf->curs_line;
78 p = buf->curs1;
79
80 if (line < l)
81 p = edit_buffer_get_backward_offset (buf, p, l - line);
82 else if (line > l)
83 p = edit_buffer_get_forward_offset (buf, p, line - l, 0);
84
85 p = edit_buffer_get_bol (buf, p);
86 while (strchr ("\t ", edit_buffer_get_byte (buf, p)) != NULL)
87 p++;
88 return p;
89 }
90
91
92
93 static gboolean
94 bad_line_start (const edit_buffer_t *buf, off_t p)
95 {
96 int c;
97
98 c = edit_buffer_get_byte (buf, p);
99 if (c == '.')
100 {
101
102 return !(edit_buffer_get_byte (buf, p + 1) == '.'
103 && edit_buffer_get_byte (buf, p + 2) == '.');
104 }
105 if (c == '-')
106 {
107
108 return !(edit_buffer_get_byte (buf, p + 1) == '-'
109 && edit_buffer_get_byte (buf, p + 2) == '-');
110 }
111
112 return (edit_options.stop_format_chars != NULL
113 && strchr (edit_options.stop_format_chars, c) != NULL);
114 }
115
116
117
118
119
120
121
122 static off_t
123 begin_paragraph (WEdit *edit, gboolean force, long *lines)
124 {
125 long i;
126
127 for (i = edit->buffer.curs_line - 1; i >= 0; i--)
128 if (edit_line_is_blank (edit, i)
129 || (force && bad_line_start (&edit->buffer, line_start (&edit->buffer, i))))
130 {
131 i++;
132 break;
133 }
134
135 *lines = edit->buffer.curs_line - i;
136
137 return edit_buffer_get_backward_offset (&edit->buffer,
138 edit_buffer_get_current_bol (&edit->buffer), *lines);
139 }
140
141
142
143
144
145
146
147 static off_t
148 end_paragraph (WEdit *edit, gboolean force)
149 {
150 long i;
151
152 for (i = edit->buffer.curs_line + 1; i <= edit->buffer.lines; i++)
153 if (edit_line_is_blank (edit, i)
154 || (force && bad_line_start (&edit->buffer, line_start (&edit->buffer, i))))
155 {
156 i--;
157 break;
158 }
159
160 return edit_buffer_get_eol (
161 &edit->buffer,
162 edit_buffer_get_forward_offset (&edit->buffer, edit_buffer_get_current_bol (&edit->buffer),
163 i - edit->buffer.curs_line, 0));
164 }
165
166
167
168 static GString *
169 get_paragraph (const edit_buffer_t *buf, off_t p, off_t q, gboolean indent)
170 {
171 GString *t;
172
173 t = g_string_sized_new (128);
174
175 for (; p < q; p++)
176 {
177 if (indent && edit_buffer_get_byte (buf, p - 1) == '\n')
178 while (strchr ("\t ", edit_buffer_get_byte (buf, p)) != NULL)
179 p++;
180
181 g_string_append_c (t, edit_buffer_get_byte (buf, p));
182 }
183
184 g_string_append_c (t, '\n');
185
186 return t;
187 }
188
189
190
191 static inline void
192 strip_newlines (unsigned char *t, off_t size)
193 {
194 unsigned char *p;
195
196 for (p = t; size-- != 0; p++)
197 if (*p == '\n')
198 *p = ' ';
199 }
200
201
202
203
204
205
206 static inline off_t
207 next_tab_pos (off_t x)
208 {
209 x += TAB_SIZE - x % TAB_SIZE;
210 return x;
211 }
212
213
214
215 static inline off_t
216 line_pixel_length (unsigned char *t, off_t b, off_t l, gboolean utf8)
217 {
218 off_t xn, x;
219 off_t char_length = 0;
220
221 #ifndef HAVE_CHARSET
222 (void) utf8;
223 #endif
224
225 for (xn = 0, x = 0; xn <= l; x = xn)
226 {
227 char *tb;
228
229 b += char_length;
230 tb = (char *) t + b;
231 char_length = 1;
232
233 switch (tb[0])
234 {
235 case '\n':
236 return b;
237 case '\t':
238 xn = next_tab_pos (x);
239 break;
240 default:
241 #ifdef HAVE_CHARSET
242 if (utf8)
243 {
244 gunichar ch;
245
246 ch = g_utf8_get_char_validated (tb, -1);
247 if (ch != (gunichar) (-2) && ch != (gunichar) (-1))
248 {
249 char *next_ch;
250
251
252 next_ch = g_utf8_next_char (tb);
253 char_length = next_ch - tb;
254
255 if (g_unichar_iswide (ch))
256 x++;
257 }
258 }
259 #endif
260
261 xn = x + 1;
262 break;
263 }
264 }
265
266 return b;
267 }
268
269
270
271 static off_t
272 next_word_start (unsigned char *t, off_t q, off_t size)
273 {
274 off_t i;
275 gboolean saw_ws = FALSE;
276
277 for (i = q; i < size; i++)
278 {
279 switch (t[i])
280 {
281 case '\n':
282 return -1;
283 case '\t':
284 case ' ':
285 saw_ws = TRUE;
286 break;
287 default:
288 if (saw_ws)
289 return i;
290 break;
291 }
292 }
293 return (-1);
294 }
295
296
297
298
299 static inline int
300 word_start (unsigned char *t, off_t q, off_t size)
301 {
302 off_t i;
303
304 if (whitespace (t[q]))
305 return next_word_start (t, q, size);
306
307 for (i = q;; i--)
308 {
309 unsigned char c;
310
311 if (i == 0)
312 return (-1);
313 c = t[i - 1];
314 if (c == '\n')
315 return (-1);
316 if (whitespace (c))
317 return i;
318 }
319 }
320
321
322
323
324 static inline void
325 format_this (unsigned char *t, off_t size, long indent, gboolean utf8)
326 {
327 off_t q = 0, ww;
328
329 strip_newlines (t, size);
330 ww = edit_options.word_wrap_line_length * FONT_MEAN_WIDTH - indent;
331 if (ww < FONT_MEAN_WIDTH * 2)
332 ww = FONT_MEAN_WIDTH * 2;
333
334 while (TRUE)
335 {
336 off_t p;
337
338 q = line_pixel_length (t, q, ww, utf8);
339 if (q > size)
340 break;
341 if (t[q] == '\n')
342 break;
343 p = word_start (t, q, size);
344 if (p == -1)
345 q = next_word_start (t, q, size);
346
347
348 else
349 q = p;
350 if (q == -1)
351 break;
352 if (q != 0)
353 t[q - 1] = '\n';
354 }
355 }
356
357
358
359 static inline void
360 replace_at (WEdit *edit, off_t q, int c)
361 {
362 edit_cursor_move (edit, q - edit->buffer.curs1);
363 edit_delete (edit, TRUE);
364 edit_insert_ahead (edit, c);
365 }
366
367
368
369 static long
370 edit_indent_width (const WEdit *edit, off_t p)
371 {
372 off_t q = p;
373
374
375 while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, q)) != NULL
376 && q < edit->buffer.size - 1)
377 q++;
378
379 return (long) edit_move_forward3 (edit, p, 0, q);
380 }
381
382
383
384 static void
385 edit_insert_indent (WEdit *edit, long indent)
386 {
387 if (!edit_options.fill_tabs_with_spaces)
388 while (indent >= TAB_SIZE)
389 {
390 edit_insert (edit, '\t');
391 indent -= TAB_SIZE;
392 }
393
394 while (indent-- > 0)
395 edit_insert (edit, ' ');
396 }
397
398
399
400
401 static inline void
402 put_paragraph (WEdit *edit, unsigned char *t, off_t p, long indent, off_t size)
403 {
404 off_t cursor;
405 off_t i;
406 int c = '\0';
407
408 cursor = edit->buffer.curs1;
409 if (indent != 0)
410 while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, p)) != NULL)
411 p++;
412 for (i = 0; i < size; i++, p++)
413 {
414 if (i != 0 && indent != 0)
415 {
416 if (t[i - 1] == '\n' && c == '\n')
417 {
418 while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, p)) != NULL)
419 p++;
420 }
421 else if (t[i - 1] == '\n')
422 {
423 off_t curs;
424
425 edit_cursor_move (edit, p - edit->buffer.curs1);
426 curs = edit->buffer.curs1;
427 edit_insert_indent (edit, indent);
428 if (cursor >= curs)
429 cursor += edit->buffer.curs1 - p;
430 p = edit->buffer.curs1;
431 }
432 else if (c == '\n')
433 {
434 edit_cursor_move (edit, p - edit->buffer.curs1);
435 while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, p)) != NULL)
436 {
437 edit_delete (edit, TRUE);
438 if (cursor > edit->buffer.curs1)
439 cursor--;
440 }
441 p = edit->buffer.curs1;
442 }
443 }
444
445 c = edit_buffer_get_byte (&edit->buffer, p);
446 if (c != t[i])
447 replace_at (edit, p, t[i]);
448 }
449 edit_cursor_move (edit, cursor - edit->buffer.curs1);
450 }
451
452
453
454 static inline long
455 test_indent (const WEdit *edit, off_t p, off_t q)
456 {
457 long indent;
458
459 indent = edit_indent_width (edit, p++);
460 if (indent == 0)
461 return 0;
462
463 for (; p < q; p++)
464 if (edit_buffer_get_byte (&edit->buffer, p - 1) == '\n'
465 && indent != edit_indent_width (edit, p))
466 return 0;
467 return indent;
468 }
469
470
471
472
473
474 void
475 format_paragraph (WEdit *edit, gboolean force)
476 {
477 off_t p, q;
478 long lines;
479 off_t size;
480 GString *t;
481 long indent;
482 unsigned char *t2;
483 gboolean utf8 = FALSE;
484
485 if (edit_options.word_wrap_line_length < 2)
486 return;
487 if (edit_line_is_blank (edit, edit->buffer.curs_line))
488 return;
489
490 p = begin_paragraph (edit, force, &lines);
491 q = end_paragraph (edit, force);
492 indent = test_indent (edit, p, q);
493
494 t = get_paragraph (&edit->buffer, p, q, indent != 0);
495 size = t->len - 1;
496
497 if (!force)
498 {
499 off_t i;
500 char *stop_format_chars;
501
502 if (edit_options.stop_format_chars != NULL
503 && strchr (edit_options.stop_format_chars, t->str[0]) != NULL)
504 {
505 g_string_free (t, TRUE);
506 return;
507 }
508
509 if (edit_options.stop_format_chars == NULL || *edit_options.stop_format_chars == '\0')
510 stop_format_chars = g_strdup ("\t");
511 else
512 stop_format_chars = g_strconcat (edit_options.stop_format_chars, "\t", (char *) NULL);
513
514 for (i = 0; i < size - 1; i++)
515 if (t->str[i] == '\n' && strchr (stop_format_chars, t->str[i + 1]) != NULL)
516 {
517 g_free (stop_format_chars);
518 g_string_free (t, TRUE);
519 return;
520 }
521
522 g_free (stop_format_chars);
523 }
524
525 t2 = (unsigned char *) g_string_free (t, FALSE);
526 #ifdef HAVE_CHARSET
527 utf8 = edit->utf8;
528 #endif
529 format_this (t2, q - p, indent, utf8);
530 put_paragraph (edit, t2, p, indent, size);
531 g_free ((char *) t2);
532
533
534 edit_scroll_left (edit, -edit->start_col);
535 }
536
537