comparison src/insdel.c @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents 56c54cf7c5b6
children 0d2f883870bc
comparison
equal deleted inserted replaced
69:804d1389bcd6 70:131b0175ea99
250 { \ 250 { \
251 (buf)->text->z = (bival); \ 251 (buf)->text->z = (bival); \
252 (buf)->text->bufz = (val); \ 252 (buf)->text->bufz = (val); \
253 } while (0) 253 } while (0)
254 254
255 /* Under Mule, we maintain two sentinels in the buffer: one at the
256 beginning of the gap, and one at the end of the buffer. This
257 allows us to move forward, examining bytes looking for the
258 end of a character, and not worry about running off the end.
259 We do not need corresponding sentinels when moving backwards
260 because we do not have to look past the beginning of a character
261 to find the beginning of the character.
262
263 Every time we change the beginning of the gap, we have to
264 call SET_GAP_SENTINEL().
265
266 Every time we change the total size (characters plus gap)
267 of the buffer, we have to call SET_END_SENTINEL().
268 */
269
270
271 #ifdef MULE
272 # define GAP_CAN_HOLD_SIZE_P(buf, len) (BUF_GAP_SIZE (buf) >= (len) + 1)
273 # define SET_GAP_SENTINEL(buf) (*BUF_GPT_ADDR (buf) = 0)
274 # define BUF_END_SENTINEL_SIZE 1
275 # define SET_END_SENTINEL(buf) \
276 (*(BUF_BEG_ADDR (buf) + BUF_GAP_SIZE (buf) + BI_BUF_Z (buf) - 1) = 0)
277 #else
255 # define GAP_CAN_HOLD_SIZE_P(buf, len) (BUF_GAP_SIZE (buf) >= (len)) 278 # define GAP_CAN_HOLD_SIZE_P(buf, len) (BUF_GAP_SIZE (buf) >= (len))
256 # define SET_GAP_SENTINEL(buf) 279 # define SET_GAP_SENTINEL(buf)
257 # define BUF_END_SENTINEL_SIZE 0 280 # define BUF_END_SENTINEL_SIZE 0
258 # define SET_END_SENTINEL(buf) 281 # define SET_END_SENTINEL(buf)
282 #endif
259 283
260 284
261 /************************************************************************/ 285 /************************************************************************/
262 /* Charcount/Bytecount conversion */ 286 /* Charcount/Bytecount conversion */
263 /************************************************************************/ 287 /************************************************************************/
264 288
265 /* Optimization. Do it. Live it. Love it. */ 289 /* Optimization. Do it. Live it. Love it. */
290
291 #ifdef MULE
292
293 /* We include the basic functions here that require no specific
294 knowledge of how data is Mule-encoded into a buffer other
295 than the basic (00 - 7F), (80 - 9F), (A0 - FF) scheme.
296 Anything that requires more specific knowledge goes into
297 mule-charset.c. */
298
299 /* Given a pointer to a text string and a length in bytes, return
300 the equivalent length in characters. */
301
302 Charcount
303 bytecount_to_charcount (CONST Bufbyte *ptr, Bytecount len)
304 {
305 Charcount count = 0;
306 CONST Bufbyte *end = ptr + len;
307
308 #if (LONGBITS == 32 || LONGBITS == 64)
309
310 # if (LONGBITS == 32)
311 # define LONG_BYTES 4
312 # define ALIGN_MASK 0xFFFFFFFCU
313 # define HIGH_BIT_MASK 0x80808080U
314 # else
315 # define LONG_BYTES 8
316 # define ALIGN_MASK 0xFFFFFFFFFFFFFFF8U
317 /* I had a dream, I was being overrun with early Intel processors ... */
318 # define HIGH_BIT_MASK 0x8080808080808080U
319 # endif
320
321 /* When we have a large number of bytes to scan, we can be trickier
322 and significantly faster by scanning them in chunks of the CPU word
323 size (assuming that they're all ASCII -- we cut out as soon as
324 we find something non-ASCII). */
325 if (len >= 12)
326 {
327 /* Determine the section in the middle of the string that's
328 amenable to this treatment. Everything has to be aligned
329 on CPU word boundaries. */
330 CONST Bufbyte *aligned_ptr =
331 (CONST Bufbyte *) (((unsigned long) (ptr + LONG_BYTES - 1)) &
332 ALIGN_MASK);
333 CONST Bufbyte *aligned_end =
334 (CONST Bufbyte *) (((unsigned long) end) & ALIGN_MASK);
335
336 /* Handle unaligned stuff at the beginning. */
337 while (ptr < aligned_ptr)
338 {
339 if (!BYTE_ASCII_P (*ptr))
340 goto bail;
341 count++, ptr++;
342 }
343 /* Now do it. */
344 while (ptr < aligned_end)
345 {
346
347 if ((* (unsigned long *) ptr) & HIGH_BIT_MASK)
348 goto bail;
349 ptr += LONG_BYTES;
350 count += LONG_BYTES;
351 }
352 }
353
354 #endif /* LONGBITS == 32 || LONGBITS == 64 */
355
356 bail:
357 while (ptr < end)
358 {
359 count++;
360 INC_CHARPTR (ptr);
361 }
362 #ifdef ERROR_CHECK_BUFPOS
363 /* Bomb out if the specified substring ends in the middle
364 of a character. Note that we might have already gotten
365 a core dump above from an invalid reference, but at least
366 we will get no farther than here. */
367 assert (ptr == end);
368 #endif
369
370 return count;
371 }
372
373 /* Given a pointer to a text string and a length in characters, return
374 the equivalent length in bytes. */
375
376 Bytecount
377 charcount_to_bytecount (CONST Bufbyte *ptr, Charcount len)
378 {
379 CONST Bufbyte *newptr = ptr;
380
381 while (len > 0)
382 {
383 INC_CHARPTR (newptr);
384 len--;
385 }
386 return newptr - ptr;
387 }
388
389 /* The next two functions are the actual meat behind the
390 bufpos-to-bytind and bytind-to-bufpos conversions. Currently
391 the method they use is fairly unsophisticated; see buffer.h.
392
393 Note that bufpos_to_bytind_func() is probably the most-called
394 function in all of XEmacs. Therefore, it must be FAST FAST FAST.
395 This is the reason why so much of the code is duplicated.
396
397 Similar considerations apply to bytind_to_bufpos_func(), although
398 less so because the function is not called so often.
399
400 #### At some point this should use a more sophisticated method;
401 see buffer.h. */
402
403 static int not_very_random_number;
404
405 Bytind
406 bufpos_to_bytind_func (struct buffer *buf, Bufpos x)
407 {
408 Bufpos bufmin;
409 Bufpos bufmax;
410 Bytind bytmin;
411 Bytind bytmax;
412 int size;
413 int forward_p;
414 Bytind retval;
415 int diff_so_far;
416 int add_to_cache = 0;
417
418 /* Check for some cached positions, for speed. */
419 if (x == BUF_PT (buf))
420 return BI_BUF_PT (buf);
421 if (x == BUF_ZV (buf))
422 return BI_BUF_ZV (buf);
423 if (x == BUF_BEGV (buf))
424 return BI_BUF_BEGV (buf);
425
426 bufmin = buf->text->mule_bufmin;
427 bufmax = buf->text->mule_bufmax;
428 bytmin = buf->text->mule_bytmin;
429 bytmax = buf->text->mule_bytmax;
430 size = (1 << buf->text->mule_shifter) + !!buf->text->mule_three_p;
431
432 /* The basic idea here is that we shift the "known region" up or down
433 until it overlaps the specified position. We do this by moving
434 the upper bound of the known region up one character at a time,
435 and moving the lower bound of the known region up as necessary
436 when the size of the character just seen changes.
437
438 We optimize this, however, by first shifting the known region to
439 one of the cached points if it's close by. (We don't check BEG or
440 Z, even though they're cached; most of the time these will be the
441 same as BEGV and ZV, and when they're not, they're not likely
442 to be used.) */
443
444 if (x > bufmax)
445 {
446 Bufpos diffmax = x - bufmax;
447 Bufpos diffpt = x - BUF_PT (buf);
448 Bufpos diffzv = BUF_ZV (buf) - x;
449 /* #### This value could stand some more exploration. */
450 Charcount heuristic_hack = (bufmax - bufmin) >> 2;
451
452 /* Check if the position is closer to PT or ZV than to the
453 end of the known region. */
454
455 if (diffpt < 0)
456 diffpt = -diffpt;
457 if (diffzv < 0)
458 diffzv = -diffzv;
459
460 /* But also implement a heuristic that favors the known region
461 over PT or ZV. The reason for this is that switching to
462 PT or ZV will wipe out the knowledge in the known region,
463 which might be annoying if the known region is large and
464 PT or ZV is not that much closer than the end of the known
465 region. */
466
467 diffzv += heuristic_hack;
468 diffpt += heuristic_hack;
469 if (diffpt < diffmax && diffpt <= diffzv)
470 {
471 bufmax = bufmin = BUF_PT (buf);
472 bytmax = bytmin = BI_BUF_PT (buf);
473 /* We set the size to 1 even though it doesn't really
474 matter because the new known region contains no
475 characters. We do this because this is the most
476 likely size of the characters around the new known
477 region, and we avoid potential yuckiness that is
478 done when size == 3. */
479 size = 1;
480 }
481 if (diffzv < diffmax)
482 {
483 bufmax = bufmin = BUF_ZV (buf);
484 bytmax = bytmin = BI_BUF_ZV (buf);
485 size = 1;
486 }
487 }
488 #ifdef ERROR_CHECK_BUFPOS
489 else if (x >= bufmin)
490 abort ();
491 #endif
492 else
493 {
494 Bufpos diffmin = bufmin - x;
495 Bufpos diffpt = BUF_PT (buf) - x;
496 Bufpos diffbegv = x - BUF_BEGV (buf);
497 /* #### This value could stand some more exploration. */
498 Charcount heuristic_hack = (bufmax - bufmin) >> 2;
499
500 if (diffpt < 0)
501 diffpt = -diffpt;
502 if (diffbegv < 0)
503 diffbegv = -diffbegv;
504
505 /* But also implement a heuristic that favors the known region --
506 see above. */
507
508 diffbegv += heuristic_hack;
509 diffpt += heuristic_hack;
510
511 if (diffpt < diffmin && diffpt <= diffbegv)
512 {
513 bufmax = bufmin = BUF_PT (buf);
514 bytmax = bytmin = BI_BUF_PT (buf);
515 /* We set the size to 1 even though it doesn't really
516 matter because the new known region contains no
517 characters. We do this because this is the most
518 likely size of the characters around the new known
519 region, and we avoid potential yuckiness that is
520 done when size == 3. */
521 size = 1;
522 }
523 if (diffbegv < diffmin)
524 {
525 bufmax = bufmin = BUF_BEGV (buf);
526 bytmax = bytmin = BI_BUF_BEGV (buf);
527 size = 1;
528 }
529 }
530
531 diff_so_far = x > bufmax ? x - bufmax : bufmin - x;
532 if (diff_so_far > 50)
533 {
534 /* If we have to move more than a certain amount, then look
535 into our cache. */
536 int minval = INT_MAX;
537 int found = 0;
538 int i;
539
540 add_to_cache = 1;
541 /* I considered keeping the positions ordered. This would speed
542 up this loop, but updating the cache would take longer, so
543 it doesn't seem like it would really matter. */
544 for (i = 0; i < 16; i++)
545 {
546 int diff = buf->text->mule_bufpos_cache[i] - x;
547
548 if (diff < 0)
549 diff = -diff;
550 if (diff < minval)
551 {
552 minval = diff;
553 found = i;
554 }
555 }
556
557 if (minval < diff_so_far)
558 {
559 bufmax = bufmin = buf->text->mule_bufpos_cache[found];
560 bytmax = bytmin = buf->text->mule_bytind_cache[found];
561 size = 1;
562 }
563 }
564
565 /* It's conceivable that the caching above could lead to X being
566 the same as one of the range edges. */
567 if (x >= bufmax)
568 {
569 Bytind newmax;
570 Bytecount newsize;
571
572 forward_p = 1;
573 while (x > bufmax)
574 {
575 newmax = bytmax;
576
577 INC_BYTIND (buf, newmax);
578 newsize = newmax - bytmax;
579 if (newsize != size)
580 {
581 bufmin = bufmax;
582 bytmin = bytmax;
583 size = newsize;
584 }
585 bytmax = newmax;
586 bufmax++;
587 }
588 retval = bytmax;
589
590 /* #### Should go past the found location to reduce the number
591 of times that this function is called */
592 }
593 else /* x < bufmin */
594 {
595 Bytind newmin;
596 Bytecount newsize;
597
598 forward_p = 0;
599 while (x < bufmin)
600 {
601 newmin = bytmin;
602
603 DEC_BYTIND (buf, newmin);
604 newsize = bytmin - newmin;
605 if (newsize != size)
606 {
607 bufmax = bufmin;
608 bytmax = bytmin;
609 size = newsize;
610 }
611 bytmin = newmin;
612 bufmin--;
613 }
614 retval = bytmin;
615
616 /* #### Should go past the found location to reduce the number
617 of times that this function is called
618 */
619 }
620
621 /* If size is three, than we have to max sure that the range we
622 discovered isn't too large, because we use a fixed-length
623 table to divide by 3. */
624
625 if (size == 3)
626 {
627 int gap = bytmax - bytmin;
628 buf->text->mule_three_p = 1;
629 buf->text->mule_shifter = 1;
630
631 if (gap > MAX_BYTIND_GAP_SIZE_3)
632 {
633 if (forward_p)
634 {
635 bytmin = bytmax - MAX_BYTIND_GAP_SIZE_3;
636 bufmin = bufmax - MAX_BUFPOS_GAP_SIZE_3;
637 }
638 else
639 {
640 bytmax = bytmin + MAX_BYTIND_GAP_SIZE_3;
641 bufmax = bufmin + MAX_BUFPOS_GAP_SIZE_3;
642 }
643 }
644 }
645 else
646 {
647 buf->text->mule_three_p = 0;
648 if (size == 4)
649 buf->text->mule_shifter = 2;
650 else
651 buf->text->mule_shifter = size - 1;
652 }
653
654 buf->text->mule_bufmin = bufmin;
655 buf->text->mule_bufmax = bufmax;
656 buf->text->mule_bytmin = bytmin;
657 buf->text->mule_bytmax = bytmax;
658
659 if (add_to_cache)
660 {
661 int replace_loc;
662
663 /* We throw away a "random" cached value and replace it with
664 the new value. It doesn't actually have to be very random
665 at all, just evenly distributed.
666
667 #### It would be better to use a least-recently-used algorithm
668 or something that tries to space things out, but I'm not sure
669 it's worth it to go to the trouble of maintaining that. */
670 not_very_random_number += 621;
671 replace_loc = not_very_random_number & 15;
672 buf->text->mule_bufpos_cache[replace_loc] = x;
673 buf->text->mule_bytind_cache[replace_loc] = retval;
674 }
675
676 return retval;
677 }
678
679 /* The logic in this function is almost identical to the logic in
680 the previous function. */
681
682 Bufpos
683 bytind_to_bufpos_func (struct buffer *buf, Bytind x)
684 {
685 Bufpos bufmin;
686 Bufpos bufmax;
687 Bytind bytmin;
688 Bytind bytmax;
689 int size;
690 int forward_p;
691 Bufpos retval;
692 int diff_so_far;
693 int add_to_cache = 0;
694
695 /* Check for some cached positions, for speed. */
696 if (x == BI_BUF_PT (buf))
697 return BUF_PT (buf);
698 if (x == BI_BUF_ZV (buf))
699 return BUF_ZV (buf);
700 if (x == BI_BUF_BEGV (buf))
701 return BUF_BEGV (buf);
702
703 bufmin = buf->text->mule_bufmin;
704 bufmax = buf->text->mule_bufmax;
705 bytmin = buf->text->mule_bytmin;
706 bytmax = buf->text->mule_bytmax;
707 size = (1 << buf->text->mule_shifter) + !!buf->text->mule_three_p;
708
709 /* The basic idea here is that we shift the "known region" up or down
710 until it overlaps the specified position. We do this by moving
711 the upper bound of the known region up one character at a time,
712 and moving the lower bound of the known region up as necessary
713 when the size of the character just seen changes.
714
715 We optimize this, however, by first shifting the known region to
716 one of the cached points if it's close by. (We don't check BI_BEG or
717 BI_Z, even though they're cached; most of the time these will be the
718 same as BI_BEGV and BI_ZV, and when they're not, they're not likely
719 to be used.) */
720
721 if (x > bytmax)
722 {
723 Bytind diffmax = x - bytmax;
724 Bytind diffpt = x - BI_BUF_PT (buf);
725 Bytind diffzv = BI_BUF_ZV (buf) - x;
726 /* #### This value could stand some more exploration. */
727 Bytecount heuristic_hack = (bytmax - bytmin) >> 2;
728
729 /* Check if the position is closer to PT or ZV than to the
730 end of the known region. */
731
732 if (diffpt < 0)
733 diffpt = -diffpt;
734 if (diffzv < 0)
735 diffzv = -diffzv;
736
737 /* But also implement a heuristic that favors the known region
738 over BI_PT or BI_ZV. The reason for this is that switching to
739 BI_PT or BI_ZV will wipe out the knowledge in the known region,
740 which might be annoying if the known region is large and
741 BI_PT or BI_ZV is not that much closer than the end of the known
742 region. */
743
744 diffzv += heuristic_hack;
745 diffpt += heuristic_hack;
746 if (diffpt < diffmax && diffpt <= diffzv)
747 {
748 bufmax = bufmin = BUF_PT (buf);
749 bytmax = bytmin = BI_BUF_PT (buf);
750 /* We set the size to 1 even though it doesn't really
751 matter because the new known region contains no
752 characters. We do this because this is the most
753 likely size of the characters around the new known
754 region, and we avoid potential yuckiness that is
755 done when size == 3. */
756 size = 1;
757 }
758 if (diffzv < diffmax)
759 {
760 bufmax = bufmin = BUF_ZV (buf);
761 bytmax = bytmin = BI_BUF_ZV (buf);
762 size = 1;
763 }
764 }
765 #ifdef ERROR_CHECK_BUFPOS
766 else if (x >= bytmin)
767 abort ();
768 #endif
769 else
770 {
771 Bytind diffmin = bytmin - x;
772 Bytind diffpt = BI_BUF_PT (buf) - x;
773 Bytind diffbegv = x - BI_BUF_BEGV (buf);
774 /* #### This value could stand some more exploration. */
775 Bytecount heuristic_hack = (bytmax - bytmin) >> 2;
776
777 if (diffpt < 0)
778 diffpt = -diffpt;
779 if (diffbegv < 0)
780 diffbegv = -diffbegv;
781
782 /* But also implement a heuristic that favors the known region --
783 see above. */
784
785 diffbegv += heuristic_hack;
786 diffpt += heuristic_hack;
787
788 if (diffpt < diffmin && diffpt <= diffbegv)
789 {
790 bufmax = bufmin = BUF_PT (buf);
791 bytmax = bytmin = BI_BUF_PT (buf);
792 /* We set the size to 1 even though it doesn't really
793 matter because the new known region contains no
794 characters. We do this because this is the most
795 likely size of the characters around the new known
796 region, and we avoid potential yuckiness that is
797 done when size == 3. */
798 size = 1;
799 }
800 if (diffbegv < diffmin)
801 {
802 bufmax = bufmin = BUF_BEGV (buf);
803 bytmax = bytmin = BI_BUF_BEGV (buf);
804 size = 1;
805 }
806 }
807
808 diff_so_far = x > bytmax ? x - bytmax : bytmin - x;
809 if (diff_so_far > 50)
810 {
811 /* If we have to move more than a certain amount, then look
812 into our cache. */
813 int minval = INT_MAX;
814 int found = 0;
815 int i;
816
817 add_to_cache = 1;
818 /* I considered keeping the positions ordered. This would speed
819 up this loop, but updating the cache would take longer, so
820 it doesn't seem like it would really matter. */
821 for (i = 0; i < 16; i++)
822 {
823 int diff = buf->text->mule_bytind_cache[i] - x;
824
825 if (diff < 0)
826 diff = -diff;
827 if (diff < minval)
828 {
829 minval = diff;
830 found = i;
831 }
832 }
833
834 if (minval < diff_so_far)
835 {
836 bufmax = bufmin = buf->text->mule_bufpos_cache[found];
837 bytmax = bytmin = buf->text->mule_bytind_cache[found];
838 size = 1;
839 }
840 }
841
842 /* It's conceivable that the caching above could lead to X being
843 the same as one of the range edges. */
844 if (x >= bytmax)
845 {
846 Bytind newmax;
847 Bytecount newsize;
848
849 forward_p = 1;
850 while (x > bytmax)
851 {
852 newmax = bytmax;
853
854 INC_BYTIND (buf, newmax);
855 newsize = newmax - bytmax;
856 if (newsize != size)
857 {
858 bufmin = bufmax;
859 bytmin = bytmax;
860 size = newsize;
861 }
862 bytmax = newmax;
863 bufmax++;
864 }
865 retval = bufmax;
866
867 /* #### Should go past the found location to reduce the number
868 of times that this function is called */
869 }
870 else /* x <= bytmin */
871 {
872 Bytind newmin;
873 Bytecount newsize;
874
875 forward_p = 0;
876 while (x < bytmin)
877 {
878 newmin = bytmin;
879
880 DEC_BYTIND (buf, newmin);
881 newsize = bytmin - newmin;
882 if (newsize != size)
883 {
884 bufmax = bufmin;
885 bytmax = bytmin;
886 size = newsize;
887 }
888 bytmin = newmin;
889 bufmin--;
890 }
891 retval = bufmin;
892
893 /* #### Should go past the found location to reduce the number
894 of times that this function is called
895 */
896 }
897
898 /* If size is three, than we have to max sure that the range we
899 discovered isn't too large, because we use a fixed-length
900 table to divide by 3. */
901
902 if (size == 3)
903 {
904 int gap = bytmax - bytmin;
905 buf->text->mule_three_p = 1;
906 buf->text->mule_shifter = 1;
907
908 if (gap > MAX_BYTIND_GAP_SIZE_3)
909 {
910 if (forward_p)
911 {
912 bytmin = bytmax - MAX_BYTIND_GAP_SIZE_3;
913 bufmin = bufmax - MAX_BUFPOS_GAP_SIZE_3;
914 }
915 else
916 {
917 bytmax = bytmin + MAX_BYTIND_GAP_SIZE_3;
918 bufmax = bufmin + MAX_BUFPOS_GAP_SIZE_3;
919 }
920 }
921 }
922 else
923 {
924 buf->text->mule_three_p = 0;
925 if (size == 4)
926 buf->text->mule_shifter = 2;
927 else
928 buf->text->mule_shifter = size - 1;
929 }
930
931 buf->text->mule_bufmin = bufmin;
932 buf->text->mule_bufmax = bufmax;
933 buf->text->mule_bytmin = bytmin;
934 buf->text->mule_bytmax = bytmax;
935
936 if (add_to_cache)
937 {
938 int replace_loc;
939
940 /* We throw away a "random" cached value and replace it with
941 the new value. It doesn't actually have to be very random
942 at all, just evenly distributed.
943
944 #### It would be better to use a least-recently-used algorithm
945 or something that tries to space things out, but I'm not sure
946 it's worth it to go to the trouble of maintaining that. */
947 not_very_random_number += 621;
948 replace_loc = not_very_random_number & 15;
949 buf->text->mule_bufpos_cache[replace_loc] = retval;
950 buf->text->mule_bytind_cache[replace_loc] = x;
951 }
952
953 return retval;
954 }
955
956 /* Text of length BYTELENGTH and CHARLENGTH (in different units)
957 was inserted at bufpos START. */
958
959 static void
960 buffer_mule_signal_inserted_region (struct buffer *buf, Bufpos start,
961 Bytecount bytelength,
962 Charcount charlength)
963 {
964 int size = (1 << buf->text->mule_shifter) + !!buf->text->mule_three_p;
965 int i;
966
967 /* Adjust the cache of known positions. */
968 for (i = 0; i < 16; i++)
969 {
970 if (buf->text->mule_bufpos_cache[i] > start)
971 {
972 buf->text->mule_bufpos_cache[i] += charlength;
973 buf->text->mule_bytind_cache[i] += bytelength;
974 }
975 }
976
977 if (start >= buf->text->mule_bufmax)
978 return;
979
980 /* The insertion is either before the known region, in which case
981 it shoves it forward; or within the known region, in which case
982 it shoves the end forward. (But it may make the known region
983 inconsistent, so we may have to shorten it.) */
984
985 if (start <= buf->text->mule_bufmin)
986 {
987 buf->text->mule_bufmin += charlength;
988 buf->text->mule_bufmax += charlength;
989 buf->text->mule_bytmin += bytelength;
990 buf->text->mule_bytmax += bytelength;
991 }
992 else
993 {
994 Bufpos end = start + charlength;
995 /* the insertion point divides the known region in two.
996 Keep the longer half, at least, and expand into the
997 inserted chunk as much as possible. */
998
999 if (start - buf->text->mule_bufmin > buf->text->mule_bufmax - start)
1000 {
1001 Bytind bytestart = (buf->text->mule_bytmin
1002 + size * (start - buf->text->mule_bufmin));
1003 Bytind bytenew;
1004
1005 while (start < end)
1006 {
1007 bytenew = bytestart;
1008 INC_BYTIND (buf, bytenew);
1009 if (bytenew - bytestart != size)
1010 break;
1011 start++;
1012 bytestart = bytenew;
1013 }
1014 if (start != end)
1015 {
1016 buf->text->mule_bufmax = start;
1017 buf->text->mule_bytmax = bytestart;
1018 }
1019 else
1020 {
1021 buf->text->mule_bufmax += charlength;
1022 buf->text->mule_bytmax += bytelength;
1023 }
1024 }
1025 else
1026 {
1027 Bytind byteend = (buf->text->mule_bytmin
1028 + size * (start - buf->text->mule_bufmin)
1029 + bytelength);
1030 Bytind bytenew;
1031
1032 buf->text->mule_bufmax += charlength;
1033 buf->text->mule_bytmax += bytelength;
1034
1035 while (end > start)
1036 {
1037 bytenew = byteend;
1038 DEC_BYTIND (buf, bytenew);
1039 if (byteend - bytenew != size)
1040 break;
1041 end--;
1042 byteend = bytenew;
1043 }
1044 if (start != end)
1045 {
1046 buf->text->mule_bufmin = end;
1047 buf->text->mule_bytmin = byteend;
1048 }
1049 }
1050 }
1051 }
1052
1053 /* Text from START to END (equivalent in Bytinds: from BI_START to
1054 BI_END) was deleted. */
1055
1056 static void
1057 buffer_mule_signal_deleted_region (struct buffer *buf, Bufpos start,
1058 Bufpos end, Bytind bi_start,
1059 Bytind bi_end)
1060 {
1061 int i;
1062
1063 /* Adjust the cache of known positions. */
1064 for (i = 0; i < 16; i++)
1065 {
1066 /* After the end; gets shoved backward */
1067 if (buf->text->mule_bufpos_cache[i] > end)
1068 {
1069 buf->text->mule_bufpos_cache[i] -= end - start;
1070 buf->text->mule_bytind_cache[i] -= bi_end - bi_start;
1071 }
1072 /* In the range; moves to start of range */
1073 else if (buf->text->mule_bufpos_cache[i] > start)
1074 {
1075 buf->text->mule_bufpos_cache[i] = start;
1076 buf->text->mule_bytind_cache[i] = bi_start;
1077 }
1078 }
1079
1080 /* We don't care about any text after the end of the known region. */
1081
1082 end = min (end, buf->text->mule_bufmax);
1083 bi_end = min (bi_end, buf->text->mule_bytmax);
1084 if (start >= end)
1085 return;
1086
1087 /* The end of the known region offsets by the total amount of deletion,
1088 since it's all before it. */
1089
1090 buf->text->mule_bufmax -= end - start;
1091 buf->text->mule_bytmax -= bi_end - bi_start;
1092
1093 /* Now we don't care about any text after the start of the known region. */
1094
1095 end = min (end, buf->text->mule_bufmin);
1096 bi_end = min (bi_end, buf->text->mule_bytmin);
1097 if (start >= end)
1098 return;
1099
1100 buf->text->mule_bufmin -= end - start;
1101 buf->text->mule_bytmin -= bi_end - bi_start;
1102 }
1103
1104 #endif /* MULE */
266 1105
267 #ifdef ERROR_CHECK_BUFPOS 1106 #ifdef ERROR_CHECK_BUFPOS
268 1107
269 Bytind 1108 Bytind
270 bufpos_to_bytind (struct buffer *buf, Bufpos x) 1109 bufpos_to_bytind (struct buffer *buf, Bufpos x)
1217 static void 2056 static void
1218 signal_first_change (struct buffer *buf) 2057 signal_first_change (struct buffer *buf)
1219 { 2058 {
1220 /* This function can GC */ 2059 /* This function can GC */
1221 Lisp_Object buffer; 2060 Lisp_Object buffer;
1222 XSETBUFFER (buffer, current_buffer); 2061 XSETBUFFER (buffer, buf);
1223 2062
1224 if (!in_first_change) 2063 if (!in_first_change)
1225 { 2064 {
1226 if (!preparing_for_armageddon && 2065 if (!preparing_for_armageddon &&
1227 !NILP (symbol_value_in_buffer (Qfirst_change_hook, buffer))) 2066 !NILP (symbol_value_in_buffer (Qfirst_change_hook, buffer)))
1279 signal_first_change (buf); 2118 signal_first_change (buf);
1280 2119
1281 /* Now in any case run the before-change-functions if any. */ 2120 /* Now in any case run the before-change-functions if any. */
1282 2121
1283 if (!preparing_for_armageddon && 2122 if (!preparing_for_armageddon &&
1284 !EQ (buffer, Vprin1_to_string_buffer) &&
1285 (!NILP (symbol_value_in_buffer (Qbefore_change_functions, buffer)) || 2123 (!NILP (symbol_value_in_buffer (Qbefore_change_functions, buffer)) ||
1286 /* Obsolete, for compatibility */ 2124 /* Obsolete, for compatibility */
1287 !NILP (symbol_value_in_buffer (Qbefore_change_function, buffer)))) 2125 !NILP (symbol_value_in_buffer (Qbefore_change_function, buffer))))
1288 { 2126 {
1289 int speccount = specpdl_depth (); 2127 int speccount = specpdl_depth ();
1338 buf->text->changes->mc_new_end += new_end - orig_end; 2176 buf->text->changes->mc_new_end += new_end - orig_end;
1339 return; /* after-change-functions signalled when all changes done */ 2177 return; /* after-change-functions signalled when all changes done */
1340 } 2178 }
1341 2179
1342 if (!preparing_for_armageddon && 2180 if (!preparing_for_armageddon &&
1343 !EQ (buffer, Vprin1_to_string_buffer) &&
1344 (!NILP (symbol_value_in_buffer (Qafter_change_functions, buffer)) || 2181 (!NILP (symbol_value_in_buffer (Qafter_change_functions, buffer)) ||
1345 /* Obsolete, for compatibility */ 2182 /* Obsolete, for compatibility */
1346 !NILP (symbol_value_in_buffer (Qafter_change_function, buffer)))) 2183 !NILP (symbol_value_in_buffer (Qafter_change_function, buffer))))
1347 { 2184 {
1348 int speccount = specpdl_depth (); 2185 int speccount = specpdl_depth ();
1374 static void 2211 static void
1375 prepare_to_modify_buffer (struct buffer *buf, Bufpos start, Bufpos end, 2212 prepare_to_modify_buffer (struct buffer *buf, Bufpos start, Bufpos end,
1376 int lockit) 2213 int lockit)
1377 { 2214 {
1378 /* This function can GC */ 2215 /* This function can GC */
1379 /* dmoore - This function can also kill the buffer buf, the current
1380 buffer, and do anything it pleases. So if you call it, be
1381 careful. */
1382 Lisp_Object buffer;
1383 struct gcpro gcpro1;
1384
1385 barf_if_buffer_read_only (buf, start, end); 2216 barf_if_buffer_read_only (buf, start, end);
1386 2217
1387 /* if this is the first modification, see about locking the buffer's 2218 /* if this is the first modification, see about locking the buffer's
1388 file */ 2219 file */
1389 XSETBUFFER (buffer, buf);
1390 GCPRO1 (buffer);
1391 if (!NILP (buf->filename) && lockit && 2220 if (!NILP (buf->filename) && lockit &&
1392 BUF_SAVE_MODIFF (buf) >= BUF_MODIFF (buf)) 2221 BUF_SAVE_MODIFF (buf) >= BUF_MODIFF (buf))
1393 { 2222 {
1394 #ifdef CLASH_DETECTION 2223 #ifdef CLASH_DETECTION
1395 if (!NILP (buf->file_truename)) 2224 if (!NILP (buf->file_truename))
1396 /* Make binding buffer-file-name to nil effective. */ 2225 /* Make binding buffer-file-name to nil effective. */
1397 lock_file (buf->file_truename); 2226 lock_file (buf->file_truename);
1398 #else 2227 #else
2228 Lisp_Object buffer;
2229 XSETBUFFER (buffer, buf);
1399 /* At least warn if this file has changed on disk since it was visited.*/ 2230 /* At least warn if this file has changed on disk since it was visited.*/
1400 if (NILP (Fverify_visited_file_modtime (buffer)) 2231 if (NILP (Fverify_visited_file_modtime (buffer))
1401 && !NILP (Ffile_exists_p (buf->filename))) 2232 && !NILP (Ffile_exists_p (buf->filename)))
1402 call1_in_buffer (buf, intern ("ask-user-about-supersession-threat"), 2233 call1_in_buffer (buf, intern ("ask-user-about-supersession-threat"),
1403 buf->filename); 2234 buf->filename);
1404 #endif /* not CLASH_DETECTION */ 2235 #endif /* not CLASH_DETECTION */
1405 } 2236 }
1406 UNGCPRO;
1407
1408 /* #### dmoore - is this reasonable in case of buf being killed above? */
1409 if (!BUFFER_LIVE_P (buf))
1410 return;
1411 2237
1412 signal_before_change (buf, start, end); 2238 signal_before_change (buf, start, end);
1413 2239
1414 #ifdef REGION_CACHE_NEEDS_WORK 2240 #ifdef REGION_CACHE_NEEDS_WORK
1415 if (buf->newline_cache) 2241 if (buf->newline_cache)
1565 SET_BI_BUF_GPT (buf, BI_BUF_GPT (buf) + length); 2391 SET_BI_BUF_GPT (buf, BI_BUF_GPT (buf) + length);
1566 SET_BOTH_BUF_ZV (buf, BUF_ZV (buf) + cclen, BI_BUF_ZV (buf) + length); 2392 SET_BOTH_BUF_ZV (buf, BUF_ZV (buf) + cclen, BI_BUF_ZV (buf) + length);
1567 SET_BOTH_BUF_Z (buf, BUF_Z (buf) + cclen, BI_BUF_Z (buf) + length); 2393 SET_BOTH_BUF_Z (buf, BUF_Z (buf) + cclen, BI_BUF_Z (buf) + length);
1568 SET_GAP_SENTINEL (buf); 2394 SET_GAP_SENTINEL (buf);
1569 2395
2396 #ifdef MULE
2397 buffer_mule_signal_inserted_region (buf, pos, length, cclen);
2398 #endif
2399
1570 process_extents_for_insertion (make_buffer (buf), ind, length); 2400 process_extents_for_insertion (make_buffer (buf), ind, length);
1571 /* We know the gap is at IND so the cast is OK. */ 2401 /* We know the gap is at IND so the cast is OK. */
1572 adjust_markers_for_insert (buf, (Memind) ind, length); 2402 adjust_markers_for_insert (buf, (Memind) ind, length);
1573 2403
1574 /* Point logically doesn't move, but may need to be adjusted because 2404 /* Point logically doesn't move, but may need to be adjusted because
1776 SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + bc_numdel); 2606 SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + bc_numdel);
1777 SET_BOTH_BUF_ZV (buf, BUF_ZV (buf) - numdel, BI_BUF_ZV (buf) - bc_numdel); 2607 SET_BOTH_BUF_ZV (buf, BUF_ZV (buf) - numdel, BI_BUF_ZV (buf) - bc_numdel);
1778 SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BI_BUF_Z (buf) - bc_numdel); 2608 SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BI_BUF_Z (buf) - bc_numdel);
1779 SET_BI_BUF_GPT (buf, bi_from); 2609 SET_BI_BUF_GPT (buf, bi_from);
1780 SET_GAP_SENTINEL (buf); 2610 SET_GAP_SENTINEL (buf);
2611
2612 #ifdef MULE
2613 buffer_mule_signal_deleted_region (buf, from, to, bi_from, bi_to);
2614 #endif
1781 2615
1782 #ifdef ERROR_CHECK_EXTENTS 2616 #ifdef ERROR_CHECK_EXTENTS
1783 sledgehammer_extent_check (bufobj); 2617 sledgehammer_extent_check (bufobj);
1784 #endif 2618 #endif
1785 2619
1838 record_change (b, pos, 1); 2672 record_change (b, pos, 1);
1839 BUF_MODIFF (b)++; 2673 BUF_MODIFF (b)++;
1840 } 2674 }
1841 memcpy (BUF_BYTE_ADDRESS (b, pos), newstr, newlen); 2675 memcpy (BUF_BYTE_ADDRESS (b, pos), newstr, newlen);
1842 signal_after_change (b, pos, pos + 1, pos + 1); 2676 signal_after_change (b, pos, pos + 1, pos + 1);
2677
2678 /* We do not have to adjust the Mule data; we just replaced a
2679 character with another of the same number of bytes. */
1843 } 2680 }
1844 else 2681 else
1845 { 2682 {
1846 /* must implement as deletion followed by insertion. */ 2683 /* must implement as deletion followed by insertion. */
1847 buffer_delete_range (b, pos, pos + 1, 0); 2684 buffer_delete_range (b, pos, pos + 1, 0);
1948 2785
1949 void 2786 void
1950 find_charsets_in_bufbyte_string (unsigned char *charsets, CONST Bufbyte *str, 2787 find_charsets_in_bufbyte_string (unsigned char *charsets, CONST Bufbyte *str,
1951 Bytecount len) 2788 Bytecount len)
1952 { 2789 {
2790 #ifndef MULE
1953 /* Telescope this. */ 2791 /* Telescope this. */
1954 charsets[0] = 1; 2792 charsets[0] = 1;
2793 #else
2794 CONST Bufbyte *strend = str + len;
2795 memset (charsets, 0, NUM_LEADING_BYTES);
2796
2797 while (str < strend)
2798 {
2799 charsets[CHAR_LEADING_BYTE (charptr_emchar (str)) - 128] = 1;
2800 INC_CHARPTR (str);
2801 }
2802 #endif
1955 } 2803 }
1956 2804
1957 void 2805 void
1958 find_charsets_in_emchar_string (unsigned char *charsets, CONST Emchar *str, 2806 find_charsets_in_emchar_string (unsigned char *charsets, CONST Emchar *str,
1959 Charcount len) 2807 Charcount len)
1960 { 2808 {
2809 #ifndef MULE
1961 /* Telescope this. */ 2810 /* Telescope this. */
1962 charsets[0] = 1; 2811 charsets[0] = 1;
2812 #else
2813 int i;
2814
2815 memset (charsets, 0, NUM_LEADING_BYTES);
2816 for (i = 0; i < len; i++)
2817 {
2818 charsets[CHAR_LEADING_BYTE (str[i]) - 128] = 1;
2819 }
2820 #endif
1963 } 2821 }
1964 2822
1965 int 2823 int
1966 bufbyte_string_displayed_columns (CONST Bufbyte *str, Bytecount len) 2824 bufbyte_string_displayed_columns (CONST Bufbyte *str, Bytecount len)
1967 { 2825 {
1968 int cols = 0; 2826 int cols = 0;
1969 CONST Bufbyte *end = str + len; 2827 CONST Bufbyte *end = str + len;
1970 2828
1971 while (str < end) 2829 while (str < end)
1972 { 2830 {
2831 #ifdef MULE
2832 Emchar ch = charptr_emchar (str);
2833 cols += XCHARSET_COLUMNS (CHAR_CHARSET (ch));
2834 #else
1973 cols++; 2835 cols++;
2836 #endif
1974 INC_CHARPTR (str); 2837 INC_CHARPTR (str);
1975 } 2838 }
1976 2839
1977 return cols; 2840 return cols;
1978 } 2841 }
2097 2960
2098 SET_BI_BUF_GPT (b, 1); 2961 SET_BI_BUF_GPT (b, 1);
2099 SET_BOTH_BUF_Z (b, 1, 1); 2962 SET_BOTH_BUF_Z (b, 1, 1);
2100 SET_GAP_SENTINEL (b); 2963 SET_GAP_SENTINEL (b);
2101 SET_END_SENTINEL (b); 2964 SET_END_SENTINEL (b);
2965 #ifdef MULE
2966 {
2967 int i;
2968
2969 b->text->mule_bufmin = b->text->mule_bufmax = 1;
2970 b->text->mule_bytmin = b->text->mule_bytmax = 1;
2971 b->text->mule_shifter = 0;
2972 b->text->mule_three_p = 0;
2973
2974 for (i = 0; i < 16; i++)
2975 {
2976 b->text->mule_bufpos_cache[i] = 1;
2977 b->text->mule_bytind_cache[i] = 1;
2978 }
2979 }
2980 #endif
2102 2981
2103 BUF_MODIFF (b) = 1; 2982 BUF_MODIFF (b) = 1;
2104 BUF_SAVE_MODIFF (b) = 1; 2983 BUF_SAVE_MODIFF (b) = 1;
2105 2984
2106 JUST_SET_POINT (b, 1, 1); 2985 JUST_SET_POINT (b, 1, 1);