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 for (xn = 0, x = 0; xn <= l; x = xn)
222 {
223 char *tb;
224
225 b += char_length;
226 tb = (char *) t + b;
227 char_length = 1;
228
229 switch (tb[0])
230 {
231 case '\n':
232 return b;
233 case '\t':
234 xn = next_tab_pos (x);
235 break;
236 default:
237 if (utf8)
238 {
239 gunichar ch;
240
241 ch = g_utf8_get_char_validated (tb, -1);
242 if (ch != (gunichar) (-2) && ch != (gunichar) (-1))
243 {
244 char *next_ch;
245
246
247 next_ch = g_utf8_next_char (tb);
248 char_length = next_ch - tb;
249
250 if (g_unichar_iswide (ch))
251 x++;
252 }
253 }
254
255 xn = x + 1;
256 break;
257 }
258 }
259
260 return b;
261 }
262
263
264
265 static off_t
266 next_word_start (unsigned char *t, off_t q, off_t size)
267 {
268 off_t i;
269 gboolean saw_ws = FALSE;
270
271 for (i = q; i < size; i++)
272 {
273 switch (t[i])
274 {
275 case '\n':
276 return -1;
277 case '\t':
278 case ' ':
279 saw_ws = TRUE;
280 break;
281 default:
282 if (saw_ws)
283 return i;
284 break;
285 }
286 }
287 return (-1);
288 }
289
290
291
292
293 static inline int
294 word_start (unsigned char *t, off_t q, off_t size)
295 {
296 off_t i;
297
298 if (whitespace (t[q]))
299 return next_word_start (t, q, size);
300
301 for (i = q;; i--)
302 {
303 unsigned char c;
304
305 if (i == 0)
306 return (-1);
307 c = t[i - 1];
308 if (c == '\n')
309 return (-1);
310 if (whitespace (c))
311 return i;
312 }
313 }
314
315
316
317
318 static inline void
319 format_this (unsigned char *t, off_t size, long indent, gboolean utf8)
320 {
321 off_t q = 0, ww;
322
323 strip_newlines (t, size);
324 ww = edit_options.word_wrap_line_length * FONT_MEAN_WIDTH - indent;
325 if (ww < FONT_MEAN_WIDTH * 2)
326 ww = FONT_MEAN_WIDTH * 2;
327
328 while (TRUE)
329 {
330 off_t p;
331
332 q = line_pixel_length (t, q, ww, utf8);
333 if (q > size)
334 break;
335 if (t[q] == '\n')
336 break;
337 p = word_start (t, q, size);
338 if (p == -1)
339 q = next_word_start (t, q, size);
340
341
342 else
343 q = p;
344 if (q == -1)
345 break;
346 if (q != 0)
347 t[q - 1] = '\n';
348 }
349 }
350
351
352
353 static inline void
354 replace_at (WEdit *edit, off_t q, int c)
355 {
356 edit_cursor_move (edit, q - edit->buffer.curs1);
357 edit_delete (edit, TRUE);
358 edit_insert_ahead (edit, c);
359 }
360
361
362
363 static long
364 edit_indent_width (const WEdit *edit, off_t p)
365 {
366 off_t q = p;
367
368
369 while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, q)) != NULL
370 && q < edit->buffer.size - 1)
371 q++;
372
373 return (long) edit_move_forward3 (edit, p, 0, q);
374 }
375
376
377
378 static void
379 edit_insert_indent (WEdit *edit, long indent)
380 {
381 if (!edit_options.fill_tabs_with_spaces)
382 while (indent >= TAB_SIZE)
383 {
384 edit_insert (edit, '\t');
385 indent -= TAB_SIZE;
386 }
387
388 while (indent-- > 0)
389 edit_insert (edit, ' ');
390 }
391
392
393
394
395 static inline void
396 put_paragraph (WEdit *edit, unsigned char *t, off_t p, long indent, off_t size)
397 {
398 off_t cursor;
399 off_t i;
400 int c = '\0';
401
402 cursor = edit->buffer.curs1;
403 if (indent != 0)
404 while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, p)) != NULL)
405 p++;
406 for (i = 0; i < size; i++, p++)
407 {
408 if (i != 0 && indent != 0)
409 {
410 if (t[i - 1] == '\n' && c == '\n')
411 {
412 while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, p)) != NULL)
413 p++;
414 }
415 else if (t[i - 1] == '\n')
416 {
417 off_t curs;
418
419 edit_cursor_move (edit, p - edit->buffer.curs1);
420 curs = edit->buffer.curs1;
421 edit_insert_indent (edit, indent);
422 if (cursor >= curs)
423 cursor += edit->buffer.curs1 - p;
424 p = edit->buffer.curs1;
425 }
426 else if (c == '\n')
427 {
428 edit_cursor_move (edit, p - edit->buffer.curs1);
429 while (strchr ("\t ", edit_buffer_get_byte (&edit->buffer, p)) != NULL)
430 {
431 edit_delete (edit, TRUE);
432 if (cursor > edit->buffer.curs1)
433 cursor--;
434 }
435 p = edit->buffer.curs1;
436 }
437 }
438
439 c = edit_buffer_get_byte (&edit->buffer, p);
440 if (c != t[i])
441 replace_at (edit, p, t[i]);
442 }
443 edit_cursor_move (edit, cursor - edit->buffer.curs1);
444 }
445
446
447
448 static inline long
449 test_indent (const WEdit *edit, off_t p, off_t q)
450 {
451 long indent;
452
453 indent = edit_indent_width (edit, p++);
454 if (indent == 0)
455 return 0;
456
457 for (; p < q; p++)
458 if (edit_buffer_get_byte (&edit->buffer, p - 1) == '\n'
459 && indent != edit_indent_width (edit, p))
460 return 0;
461 return indent;
462 }
463
464
465
466
467
468 void
469 format_paragraph (WEdit *edit, gboolean force)
470 {
471 off_t p, q;
472 long lines;
473 off_t size;
474 GString *t;
475 long indent;
476 unsigned char *t2;
477
478 if (edit_options.word_wrap_line_length < 2)
479 return;
480 if (edit_line_is_blank (edit, edit->buffer.curs_line))
481 return;
482
483 p = begin_paragraph (edit, force, &lines);
484 q = end_paragraph (edit, force);
485 indent = test_indent (edit, p, q);
486
487 t = get_paragraph (&edit->buffer, p, q, indent != 0);
488 size = t->len - 1;
489
490 if (!force)
491 {
492 off_t i;
493 char *stop_format_chars;
494
495 if (edit_options.stop_format_chars != NULL
496 && strchr (edit_options.stop_format_chars, t->str[0]) != NULL)
497 {
498 g_string_free (t, TRUE);
499 return;
500 }
501
502 if (edit_options.stop_format_chars == NULL || *edit_options.stop_format_chars == '\0')
503 stop_format_chars = g_strdup ("\t");
504 else
505 stop_format_chars = g_strconcat (edit_options.stop_format_chars, "\t", (char *) NULL);
506
507 for (i = 0; i < size - 1; i++)
508 if (t->str[i] == '\n' && strchr (stop_format_chars, t->str[i + 1]) != NULL)
509 {
510 g_free (stop_format_chars);
511 g_string_free (t, TRUE);
512 return;
513 }
514
515 g_free (stop_format_chars);
516 }
517
518 t2 = (unsigned char *) g_string_free (t, FALSE);
519 format_this (t2, q - p, indent, edit->utf8);
520 put_paragraph (edit, t2, p, indent, size);
521 g_free ((char *) t2);
522
523
524 edit_scroll_left (edit, -edit->start_col);
525 }
526
527