# HG changeset patch # User Richard M. Stallman # Date 1049661172 0 # Node ID dc1f6aa292852b6743c510e4e7f8aac0a6b7d49f # Parent c7a0b787faef32d9cf8700235edb58db537340c7 Add many calls to CHECK_TOTAL_LENGTH. (set_intervals_multibyte_1): When becoming multibyte, adjust right and left child sizes to a whole set of characters. If an interval gets zero total-length, delete it. If an interval consists of just its children, delete one of them. diff -r c7a0b787faef -r dc1f6aa29285 src/intervals.c --- a/src/intervals.c Sun Apr 06 20:29:13 2003 +0000 +++ b/src/intervals.c Sun Apr 06 20:32:52 2003 +0000 @@ -75,12 +75,14 @@ { new->total_length = (BUF_Z (XBUFFER (parent)) - BUF_BEG (XBUFFER (parent))); + CHECK_TOTAL_LENGTH (new); BUF_INTERVALS (XBUFFER (parent)) = new; new->position = 1; } else if (STRINGP (parent)) { new->total_length = SCHARS (parent); + CHECK_TOTAL_LENGTH (new); STRING_SET_INTERVALS (parent, new); new->position = 0; } @@ -338,9 +340,11 @@ /* A's total length is decreased by the length of B and its left child. */ interval->total_length -= B->total_length - LEFT_TOTAL_LENGTH (interval); + CHECK_TOTAL_LENGTH (interval); /* B must have the same total length of A. */ B->total_length = old_total; + CHECK_TOTAL_LENGTH (B); return B; } @@ -384,9 +388,11 @@ /* A's total length is decreased by the length of B and its right child. */ interval->total_length -= B->total_length - RIGHT_TOTAL_LENGTH (interval); + CHECK_TOTAL_LENGTH (interval); /* B must have the same total length of A. */ B->total_length = old_total; + CHECK_TOTAL_LENGTH (B); return B; } @@ -405,6 +411,7 @@ old_diff = LEFT_TOTAL_LENGTH (i) - RIGHT_TOTAL_LENGTH (i); if (old_diff > 0) { + /* Since the left child is longer, there must be one. */ new_diff = i->total_length - i->left->total_length + RIGHT_TOTAL_LENGTH (i->left) - LEFT_TOTAL_LENGTH (i->left); if (abs (new_diff) >= old_diff) @@ -414,6 +421,7 @@ } else if (old_diff < 0) { + /* Since the right child is longer, there must be one. */ new_diff = i->total_length - i->right->total_length + LEFT_TOTAL_LENGTH (i->right) - RIGHT_TOTAL_LENGTH (i->right); if (abs (new_diff) >= -old_diff) @@ -514,6 +522,7 @@ { interval->right = new; new->total_length = new_length; + CHECK_TOTAL_LENGTH (new); } else { @@ -522,6 +531,7 @@ SET_INTERVAL_PARENT (interval->right, new); interval->right = new; new->total_length = new_length + new->right->total_length; + CHECK_TOTAL_LENGTH (new); balance_an_interval (new); } @@ -559,6 +569,7 @@ { interval->left = new; new->total_length = new_length; + CHECK_TOTAL_LENGTH (new); } else { @@ -567,6 +578,7 @@ SET_INTERVAL_PARENT (new->left, new); interval->left = new; new->total_length = new_length + new->left->total_length; + CHECK_TOTAL_LENGTH (new); balance_an_interval (new); } @@ -828,6 +840,7 @@ if (relative_position <= LEFT_TOTAL_LENGTH (this)) { this->total_length += length; + CHECK_TOTAL_LENGTH (this); this = this->left; } else if (relative_position > (TOTAL_LENGTH (this) @@ -836,6 +849,7 @@ relative_position -= (TOTAL_LENGTH (this) - RIGHT_TOTAL_LENGTH (this)); this->total_length += length; + CHECK_TOTAL_LENGTH (this); this = this->right; } else @@ -843,6 +857,7 @@ /* If we are to use zero-length intervals as buffer pointers, then this code will have to change. */ this->total_length += length; + CHECK_TOTAL_LENGTH (this); this->position = LEFT_TOTAL_LENGTH (this) + position - relative_position + 1; return tree; @@ -987,6 +1002,7 @@ for (temp = prev ? prev : i; temp; temp = INTERVAL_PARENT_OR_NULL (temp)) { temp->total_length += length; + CHECK_TOTAL_LENGTH (temp); temp = balance_possible_root_interval (temp); } @@ -1043,6 +1059,7 @@ for (temp = i; temp; temp = INTERVAL_PARENT_OR_NULL (temp)) { temp->total_length += length; + CHECK_TOTAL_LENGTH (temp); temp = balance_possible_root_interval (temp); } } @@ -1247,6 +1264,7 @@ this = this->left; this->total_length += migrate_amt; } + CHECK_TOTAL_LENGTH (this); this->left = migrate; SET_INTERVAL_PARENT (migrate, this); @@ -1331,6 +1349,7 @@ relative_position, amount); tree->total_length -= subtract; + CHECK_TOTAL_LENGTH (tree); return subtract; } /* Right branch */ @@ -1345,6 +1364,7 @@ relative_position, amount); tree->total_length -= subtract; + CHECK_TOTAL_LENGTH (tree); return subtract; } /* Here -- this node. */ @@ -1359,6 +1379,7 @@ amount = my_amount; tree->total_length -= amount; + CHECK_TOTAL_LENGTH (tree); if (LENGTH (tree) == 0) delete_interval (tree); @@ -1402,6 +1423,7 @@ if (ONLY_INTERVAL_P (tree)) { tree->total_length -= length; + CHECK_TOTAL_LENGTH (tree); return; } @@ -1457,6 +1479,7 @@ /* Zero out this interval. */ i->total_length -= absorb; + CHECK_TOTAL_LENGTH (i); /* Find the succeeding interval. */ if (! NULL_RIGHT_CHILD (i)) /* It's below us. Add absorb @@ -1466,10 +1489,12 @@ while (! NULL_LEFT_CHILD (successor)) { successor->total_length += absorb; + CHECK_TOTAL_LENGTH (successor); successor = successor->left; } successor->total_length += absorb; + CHECK_TOTAL_LENGTH (successor); delete_interval (i); return successor; } @@ -1487,6 +1512,7 @@ successor = INTERVAL_PARENT (successor); successor->total_length -= absorb; + CHECK_TOTAL_LENGTH (successor); } /* This must be the rightmost or last interval and cannot @@ -1510,6 +1536,7 @@ /* Zero out this interval. */ i->total_length -= absorb; + CHECK_TOTAL_LENGTH (i); /* Find the preceding interval. */ if (! NULL_LEFT_CHILD (i)) /* It's below us. Go down, @@ -1519,10 +1546,12 @@ while (! NULL_RIGHT_CHILD (predecessor)) { predecessor->total_length += absorb; + CHECK_TOTAL_LENGTH (predecessor); predecessor = predecessor->right; } predecessor->total_length += absorb; + CHECK_TOTAL_LENGTH (predecessor); delete_interval (i); return predecessor; } @@ -1540,6 +1569,7 @@ predecessor = INTERVAL_PARENT (predecessor); predecessor->total_length -= absorb; + CHECK_TOTAL_LENGTH (predecessor); } /* This must be the leftmost or first interval and cannot @@ -2354,6 +2384,7 @@ new->position = 0; got = (LENGTH (i) - (start - i->position)); new->total_length = length; + CHECK_TOTAL_LENGTH (new); copy_properties (i, new); t = new; @@ -2440,6 +2471,13 @@ i->total_length = end - start; else i->total_length = end_byte - start_byte; + CHECK_TOTAL_LENGTH (i); + + if (TOTAL_LENGTH (i) == 0) + { + delete_interval (i); + return; + } /* Recursively fix the length of the subintervals. */ if (i->left) @@ -2448,8 +2486,23 @@ if (multi_flag) { + int temp; left_end_byte = start_byte + LEFT_TOTAL_LENGTH (i); left_end = BYTE_TO_CHAR (left_end_byte); + + temp = CHAR_TO_BYTE (left_end); + + /* If LEFT_END_BYTE is in the middle of a character, + adjust it and LEFT_END to a char boundary. */ + if (left_end_byte > temp) + { + left_end_byte = temp; + } + if (left_end_byte < temp) + { + left_end--; + left_end_byte = CHAR_TO_BYTE (left_end); + } } else { @@ -2466,8 +2519,24 @@ if (multi_flag) { + int temp; + right_start_byte = end_byte - RIGHT_TOTAL_LENGTH (i); right_start = BYTE_TO_CHAR (right_start_byte); + + /* If RIGHT_START_BYTE is in the middle of a character, + adjust it and RIGHT_START to a char boundary. */ + temp = CHAR_TO_BYTE (right_start); + + if (right_start_byte < temp) + { + right_start_byte = temp; + } + if (right_start_byte > temp) + { + right_start++; + right_start_byte = CHAR_TO_BYTE (right_start); + } } else { @@ -2479,6 +2548,25 @@ right_start, right_start_byte, end, end_byte); } + + /* Rounding to char boundaries can theoretically ake this interval + spurious. If so, delete one child, and copy its property list + to this interval. */ + if (LEFT_TOTAL_LENGTH (i) + RIGHT_TOTAL_LENGTH (i) >= TOTAL_LENGTH (i)) + { + if ((i)->left) + { + (i)->plist = (i)->left->plist; + (i)->left->total_length = 0; + delete_interval ((i)->left); + } + else + { + (i)->plist = (i)->right->plist; + (i)->right->total_length = 0; + delete_interval ((i)->right); + } + } } /* Update the intervals of the current buffer