Mercurial > hg > xemacs-beta
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); |