This source file includes following definitions.
- edit_buffer_get_byte_ptr
- edit_buffer_init
- edit_buffer_clean
- edit_buffer_get_byte
- edit_buffer_get_utf
- edit_buffer_get_prev_utf
- edit_buffer_count_lines
- edit_buffer_get_bol
- edit_buffer_get_eol
- edit_buffer_get_word_from_pos
- edit_buffer_find_word_start
- edit_buffer_insert
- edit_buffer_insert_ahead
- edit_buffer_delete
- edit_buffer_backspace
- edit_buffer_get_forward_offset
- edit_buffer_get_backward_offset
- edit_buffer_read_file
- edit_buffer_write_file
- edit_buffer_calc_percent
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 #include <config.h>
33
34 #include <ctype.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
38
39 #include "lib/global.h"
40
41 #include "lib/vfs/vfs.h"
42
43 #include "edit-impl.h"
44 #include "editbuffer.h"
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 #ifndef S_EDIT_BUF_SIZE
90 #define S_EDIT_BUF_SIZE 16
91 #endif
92
93
94 #define EDIT_BUF_SIZE (((off_t) 1) << S_EDIT_BUF_SIZE)
95
96
97 #define M_EDIT_BUF_SIZE (EDIT_BUF_SIZE - 1)
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 static char *
115 edit_buffer_get_byte_ptr (const edit_buffer_t * buf, off_t byte_index)
116 {
117 void *b;
118
119 if (byte_index >= (buf->curs1 + buf->curs2) || byte_index < 0)
120 return NULL;
121
122 if (byte_index >= buf->curs1)
123 {
124 off_t p;
125
126 p = buf->curs1 + buf->curs2 - byte_index - 1;
127 b = g_ptr_array_index (buf->b2, p >> S_EDIT_BUF_SIZE);
128 return (char *) b + EDIT_BUF_SIZE - 1 - (p & M_EDIT_BUF_SIZE);
129 }
130
131 b = g_ptr_array_index (buf->b1, byte_index >> S_EDIT_BUF_SIZE);
132 return (char *) b + (byte_index & M_EDIT_BUF_SIZE);
133 }
134
135
136
137
138
139
140
141
142
143
144 void
145 edit_buffer_init (edit_buffer_t * buf, off_t size)
146 {
147 buf->b1 = g_ptr_array_sized_new (32);
148 buf->b2 = g_ptr_array_sized_new (32);
149
150 buf->curs1 = 0;
151 buf->curs2 = 0;
152
153 buf->size = size;
154 buf->lines = 0;
155 }
156
157
158
159
160
161
162
163
164 void
165 edit_buffer_clean (edit_buffer_t * buf)
166 {
167 if (buf->b1 != NULL)
168 {
169 g_ptr_array_foreach (buf->b1, (GFunc) g_free, NULL);
170 g_ptr_array_free (buf->b1, TRUE);
171 }
172
173 if (buf->b2 != NULL)
174 {
175 g_ptr_array_foreach (buf->b2, (GFunc) g_free, NULL);
176 g_ptr_array_free (buf->b2, TRUE);
177 }
178 }
179
180
181
182
183
184
185
186
187
188
189
190 int
191 edit_buffer_get_byte (const edit_buffer_t * buf, off_t byte_index)
192 {
193 char *p;
194
195 p = edit_buffer_get_byte_ptr (buf, byte_index);
196
197 return (p != NULL) ? *(unsigned char *) p : '\n';
198 }
199
200
201
202 #ifdef HAVE_CHARSET
203
204
205
206
207
208
209
210
211
212
213
214
215 int
216 edit_buffer_get_utf (const edit_buffer_t * buf, off_t byte_index, int *char_length)
217 {
218 gchar *str = NULL;
219 gunichar res;
220 gunichar ch;
221 gchar *next_ch = NULL;
222
223 if (byte_index >= (buf->curs1 + buf->curs2) || byte_index < 0)
224 {
225 *char_length = 0;
226 return '\n';
227 }
228
229 str = edit_buffer_get_byte_ptr (buf, byte_index);
230 if (str == NULL)
231 {
232 *char_length = 0;
233 return 0;
234 }
235
236 res = g_utf8_get_char_validated (str, -1);
237 if (res == (gunichar) (-2) || res == (gunichar) (-1))
238 {
239
240 size_t i;
241 gchar utf8_buf[UTF8_CHAR_LEN + 1];
242
243 for (i = 0; i < UTF8_CHAR_LEN; i++)
244 utf8_buf[i] = edit_buffer_get_byte (buf, byte_index + i);
245 utf8_buf[i] = '\0';
246 res = g_utf8_get_char_validated (utf8_buf, -1);
247 }
248
249 if (res == (gunichar) (-2) || res == (gunichar) (-1))
250 {
251 ch = *str;
252 *char_length = 0;
253 }
254 else
255 {
256 ch = res;
257
258 next_ch = g_utf8_next_char (str);
259 *char_length = next_ch - str;
260 }
261
262 return (int) ch;
263 }
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278 int
279 edit_buffer_get_prev_utf (const edit_buffer_t * buf, off_t byte_index, int *char_length)
280 {
281 size_t i;
282 gchar utf8_buf[3 * UTF8_CHAR_LEN + 1];
283 gchar *str;
284 gchar *cursor_buf_ptr;
285 gunichar res;
286
287 if (byte_index > (buf->curs1 + buf->curs2) || byte_index <= 0)
288 {
289 *char_length = 0;
290 return 0;
291 }
292
293 for (i = 0; i < (3 * UTF8_CHAR_LEN); i++)
294 utf8_buf[i] = edit_buffer_get_byte (buf, byte_index + i - (2 * UTF8_CHAR_LEN));
295 utf8_buf[i] = '\0';
296
297 cursor_buf_ptr = utf8_buf + (2 * UTF8_CHAR_LEN);
298 str = g_utf8_find_prev_char (utf8_buf, cursor_buf_ptr);
299
300 if (str == NULL || g_utf8_next_char (str) != cursor_buf_ptr)
301 {
302 *char_length = 1;
303 return *(cursor_buf_ptr - 1);
304 }
305
306 res = g_utf8_get_char_validated (str, -1);
307 if (res == (gunichar) (-2) || res == (gunichar) (-1))
308 {
309 *char_length = 1;
310 return *(cursor_buf_ptr - 1);
311 }
312
313 *char_length = cursor_buf_ptr - str;
314 return (int) res;
315 }
316 #endif
317
318
319
320
321
322
323
324
325
326
327
328
329 long
330 edit_buffer_count_lines (const edit_buffer_t * buf, off_t first, off_t last)
331 {
332 long lines = 0;
333
334 first = MAX (first, 0);
335 last = MIN (last, buf->size);
336
337 while (first < last)
338 if (edit_buffer_get_byte (buf, first++) == '\n')
339 lines++;
340
341 return lines;
342 }
343
344
345
346
347
348
349
350
351
352
353
354 off_t
355 edit_buffer_get_bol (const edit_buffer_t * buf, off_t current)
356 {
357 if (current <= 0)
358 return 0;
359
360 for (; edit_buffer_get_byte (buf, current - 1) != '\n'; current--)
361 ;
362
363 return current;
364 }
365
366
367
368
369
370
371
372
373
374
375
376 off_t
377 edit_buffer_get_eol (const edit_buffer_t * buf, off_t current)
378 {
379 if (current >= buf->size)
380 return buf->size;
381
382 for (; edit_buffer_get_byte (buf, current) != '\n'; current++)
383 ;
384
385 return current;
386 }
387
388
389
390
391
392
393
394
395
396
397
398
399
400 GString *
401 edit_buffer_get_word_from_pos (const edit_buffer_t * buf, off_t start_pos, off_t * start,
402 gsize * cut)
403 {
404 off_t word_start;
405 gsize cut_len = 0;
406 GString *match_expr;
407 int c1, c2;
408
409 for (word_start = start_pos; word_start != 0; word_start--, cut_len++)
410 {
411 c1 = edit_buffer_get_byte (buf, word_start);
412 c2 = edit_buffer_get_byte (buf, word_start - 1);
413
414 if (is_break_char (c1) != is_break_char (c2) || c1 == '\n' || c2 == '\n')
415 break;
416 }
417
418 match_expr = g_string_sized_new (16);
419
420 do
421 {
422 c1 = edit_buffer_get_byte (buf, word_start + match_expr->len);
423 c2 = edit_buffer_get_byte (buf, word_start + match_expr->len + 1);
424 g_string_append_c (match_expr, c1);
425 }
426 while (!(is_break_char (c1) != is_break_char (c2) || c1 == '\n' || c2 == '\n'));
427
428 *start = word_start;
429 *cut = cut_len;
430
431 return match_expr;
432 }
433
434
435
436
437
438
439
440
441
442
443
444
445
446 gboolean
447 edit_buffer_find_word_start (const edit_buffer_t * buf, off_t * word_start, gsize * word_len)
448 {
449 int c;
450 off_t i;
451
452
453 if (buf->curs1 <= 0)
454 return FALSE;
455
456 c = edit_buffer_get_previous_byte (buf);
457
458 if (is_break_char (c))
459 return FALSE;
460
461
462 for (i = 1;; i++)
463 {
464 int last;
465
466 last = c;
467 c = edit_buffer_get_byte (buf, buf->curs1 - i - 1);
468
469 if (is_break_char (c))
470 {
471
472 if (isdigit (last))
473 return FALSE;
474
475 break;
476 }
477 }
478
479
480 *word_start = buf->curs1 - i;
481 *word_len = (gsize) i;
482
483 return TRUE;
484 }
485
486
487
488
489
490
491
492
493
494
495 void
496 edit_buffer_insert (edit_buffer_t * buf, int c)
497 {
498 void *b;
499 off_t i;
500
501 i = buf->curs1 & M_EDIT_BUF_SIZE;
502
503
504 if (i == 0)
505 g_ptr_array_add (buf->b1, g_malloc0 (EDIT_BUF_SIZE));
506
507
508 b = g_ptr_array_index (buf->b1, buf->curs1 >> S_EDIT_BUF_SIZE);
509 *((unsigned char *) b + i) = (unsigned char) c;
510
511
512 buf->curs1++;
513
514
515 buf->size++;
516 }
517
518
519
520
521
522
523
524
525
526
527 void
528 edit_buffer_insert_ahead (edit_buffer_t * buf, int c)
529 {
530 void *b;
531 off_t i;
532
533 i = buf->curs2 & M_EDIT_BUF_SIZE;
534
535
536 if (i == 0)
537 g_ptr_array_add (buf->b2, g_malloc0 (EDIT_BUF_SIZE));
538
539
540 b = g_ptr_array_index (buf->b2, buf->curs2 >> S_EDIT_BUF_SIZE);
541 *((unsigned char *) b + EDIT_BUF_SIZE - 1 - i) = (unsigned char) c;
542
543
544 buf->curs2++;
545
546
547 buf->size++;
548 }
549
550
551
552
553
554
555
556
557
558
559 int
560 edit_buffer_delete (edit_buffer_t * buf)
561 {
562 void *b;
563 unsigned char c;
564 off_t prev;
565 off_t i;
566
567 prev = buf->curs2 - 1;
568
569 b = g_ptr_array_index (buf->b2, prev >> S_EDIT_BUF_SIZE);
570 i = prev & M_EDIT_BUF_SIZE;
571 c = *((unsigned char *) b + EDIT_BUF_SIZE - 1 - i);
572
573 if (i == 0)
574 {
575 guint j;
576
577 j = buf->b2->len - 1;
578 b = g_ptr_array_index (buf->b2, j);
579 g_ptr_array_remove_index (buf->b2, j);
580 g_free (b);
581 }
582
583 buf->curs2 = prev;
584
585
586 buf->size--;
587
588 return c;
589 }
590
591
592
593
594
595
596
597
598
599
600 int
601 edit_buffer_backspace (edit_buffer_t * buf)
602 {
603 void *b;
604 unsigned char c;
605 off_t prev;
606 off_t i;
607
608 prev = buf->curs1 - 1;
609
610 b = g_ptr_array_index (buf->b1, prev >> S_EDIT_BUF_SIZE);
611 i = prev & M_EDIT_BUF_SIZE;
612 c = *((unsigned char *) b + i);
613
614 if (i == 0)
615 {
616 guint j;
617
618 j = buf->b1->len - 1;
619 b = g_ptr_array_index (buf->b1, j);
620 g_ptr_array_remove_index (buf->b1, j);
621 g_free (b);
622 }
623
624 buf->curs1 = prev;
625
626
627 buf->size--;
628
629 return c;
630 }
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646 off_t
647 edit_buffer_get_forward_offset (const edit_buffer_t * buf, off_t current, long lines, off_t upto)
648 {
649 if (upto != 0)
650 return (off_t) edit_buffer_count_lines (buf, current, upto);
651
652 lines = MAX (lines, 0);
653
654 while (lines-- != 0)
655 {
656 long next;
657
658 next = edit_buffer_get_eol (buf, current) + 1;
659 if (next > buf->size)
660 break;
661 current = next;
662 }
663
664 return current;
665 }
666
667
668
669
670
671
672
673
674
675
676
677
678 off_t
679 edit_buffer_get_backward_offset (const edit_buffer_t * buf, off_t current, long lines)
680 {
681 lines = MAX (lines, 0);
682 current = edit_buffer_get_bol (buf, current);
683
684 while (lines-- != 0 && current != 0)
685 current = edit_buffer_get_bol (buf, current - 1);
686
687 return current;
688 }
689
690
691
692
693
694
695
696
697
698
699
700
701 off_t
702 edit_buffer_read_file (edit_buffer_t * buf, int fd, off_t size,
703 edit_buffer_read_file_status_msg_t * sm, gboolean * aborted)
704 {
705 off_t ret = 0;
706 off_t i, j;
707 off_t data_size;
708 void *b;
709 status_msg_t *s = STATUS_MSG (sm);
710 unsigned short update_cnt = 0;
711
712 *aborted = FALSE;
713
714 buf->lines = 0;
715 buf->curs2 = size;
716 i = buf->curs2 >> S_EDIT_BUF_SIZE;
717
718
719 data_size = buf->curs2 & M_EDIT_BUF_SIZE;
720 if (data_size != 0)
721 {
722 b = g_malloc0 (EDIT_BUF_SIZE);
723 g_ptr_array_add (buf->b2, b);
724 b = (char *) b + EDIT_BUF_SIZE - data_size;
725 ret = mc_read (fd, b, data_size);
726
727
728 for (j = 0; j < ret; j++)
729 if (*((char *) b + j) == '\n')
730 buf->lines++;
731
732 if (ret < 0 || ret != data_size)
733 return ret;
734 }
735
736
737 data_size = EDIT_BUF_SIZE;
738 for (--i; i >= 0; i--)
739 {
740 off_t sz;
741
742 b = g_malloc0 (data_size);
743 g_ptr_array_add (buf->b2, b);
744 sz = mc_read (fd, b, data_size);
745 if (sz >= 0)
746 ret += sz;
747
748
749 for (j = 0; j < sz; j++)
750 if (*((char *) b + j) == '\n')
751 buf->lines++;
752
753 if (s != NULL && s->update != NULL)
754 {
755 update_cnt = (update_cnt + 1) & 0xf;
756 if (update_cnt == 0)
757 {
758
759 if (sm->buf == NULL)
760 sm->buf = buf;
761
762 sm->loaded = ret;
763 if (s->update (s) == B_CANCEL)
764 {
765 *aborted = TRUE;
766 return (-1);
767 }
768 }
769 }
770
771 if (sz != data_size)
772 break;
773 }
774
775
776 for (i = 0; i < (off_t) buf->b2->len / 2; i++)
777 {
778 void **b1, **b2;
779
780 b1 = &g_ptr_array_index (buf->b2, i);
781 b2 = &g_ptr_array_index (buf->b2, buf->b2->len - 1 - i);
782
783 b = *b1;
784 *b1 = *b2;
785 *b2 = b;
786
787 if (s != NULL && s->update != NULL)
788 {
789 update_cnt = (update_cnt + 1) & 0xf;
790 if (update_cnt == 0)
791 {
792 sm->loaded = ret;
793 if (s->update (s) == B_CANCEL)
794 {
795 *aborted = TRUE;
796 return (-1);
797 }
798 }
799 }
800 }
801
802 return ret;
803 }
804
805
806
807
808
809
810
811
812
813
814
815 off_t
816 edit_buffer_write_file (edit_buffer_t * buf, int fd)
817 {
818 off_t ret = 0;
819 off_t i;
820 off_t data_size, sz;
821 void *b;
822
823
824 if (buf->b1->len != 0)
825 {
826 data_size = EDIT_BUF_SIZE;
827 for (i = 0; i < (off_t) buf->b1->len - 1; i++)
828 {
829 b = g_ptr_array_index (buf->b1, i);
830 sz = mc_write (fd, b, data_size);
831 if (sz >= 0)
832 ret += sz;
833 else if (i == 0)
834 ret = sz;
835 if (sz != data_size)
836 return ret;
837 }
838
839
840 data_size = ((buf->curs1 - 1) & M_EDIT_BUF_SIZE) + 1;
841 b = g_ptr_array_index (buf->b1, i);
842 sz = mc_write (fd, b, data_size);
843 if (sz >= 0)
844 ret += sz;
845 if (sz != data_size)
846 return ret;
847 }
848
849
850 if (buf->b2->len != 0)
851 {
852
853 i = buf->b2->len - 1;
854 b = g_ptr_array_index (buf->b2, i);
855 data_size = ((buf->curs2 - 1) & M_EDIT_BUF_SIZE) + 1;
856 sz = mc_write (fd, (char *) b + EDIT_BUF_SIZE - data_size, data_size);
857 if (sz >= 0)
858 ret += sz;
859
860 if (sz == data_size)
861 {
862
863 data_size = EDIT_BUF_SIZE;
864 while (--i >= 0)
865 {
866 b = g_ptr_array_index (buf->b2, i);
867 sz = mc_write (fd, b, data_size);
868 if (sz >= 0)
869 ret += sz;
870 if (sz != data_size)
871 break;
872 }
873 }
874 }
875
876 return ret;
877 }
878
879
880
881
882
883
884
885
886
887
888
889 int
890 edit_buffer_calc_percent (const edit_buffer_t * buf, off_t offset)
891 {
892 int percent;
893
894 if (buf->size == 0)
895 percent = 0;
896 else if (offset >= buf->size)
897 percent = 100;
898 else if (offset > (INT_MAX / 100))
899 percent = offset / (buf->size / 100);
900 else
901 percent = offset * 100 / buf->size;
902
903 return percent;
904 }
905
906