diff options
| author | Richard M. Stallman | 1998-01-01 02:35:09 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1998-01-01 02:35:09 +0000 |
| commit | 1389ad718c988c0f423facf0e953178d3e24cf30 (patch) | |
| tree | fb851ed57b5978bbbba3b164d998686ab3441553 /src | |
| parent | 12adba3450a05ca94bb250094275fc601c35aa57 (diff) | |
| download | emacs-1389ad718c988c0f423facf0e953178d3e24cf30.tar.gz emacs-1389ad718c988c0f423facf0e953178d3e24cf30.zip | |
(marker_byte_position): Renamed from marker_position.
(marker_position): New function returns the charpos.
(Fbuffer_has_markers_at): Test the marker's charpos.
(set_marker_restricted, Fset_marker): Set both kinds of position.
Optimize case where POSITION is a marker.
(set_marker_both, set_marker_restricted_both): New functions.
(Fmarker_position): Use the charpos.
(charpos_to_bytepos, bytepos_to_charpos): New functions.
(buf_charpos_to_bytepos, buf_bytepos_to_charpos): New functions.
Diffstat (limited to 'src')
| -rw-r--r-- | src/marker.c | 582 |
1 files changed, 545 insertions, 37 deletions
diff --git a/src/marker.c b/src/marker.c index 260e2b1737d..2bccb7400f5 100644 --- a/src/marker.c +++ b/src/marker.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Markers: examining, setting and killing. | 1 | /* Markers: examining, setting and deleting. |
| 2 | Copyright (C) 1985 Free Software Foundation, Inc. | 2 | Copyright (C) 1985, 1997 Free Software Foundation, Inc. |
| 3 | 3 | ||
| 4 | This file is part of GNU Emacs. | 4 | This file is part of GNU Emacs. |
| 5 | 5 | ||
| @@ -22,7 +22,345 @@ Boston, MA 02111-1307, USA. */ | |||
| 22 | #include <config.h> | 22 | #include <config.h> |
| 23 | #include "lisp.h" | 23 | #include "lisp.h" |
| 24 | #include "buffer.h" | 24 | #include "buffer.h" |
| 25 | #include "charset.h" | ||
| 25 | 26 | ||
| 27 | /* Record one cached position found recently by | ||
| 28 | buf_charpos_to_bytepos or buf_bytepos_to_charpos. */ | ||
| 29 | |||
| 30 | static int cached_charpos; | ||
| 31 | static int cached_bytepos; | ||
| 32 | static struct buffer *cached_buffer; | ||
| 33 | static int cached_modiff; | ||
| 34 | |||
| 35 | /* Converting between character positions and byte positions. */ | ||
| 36 | |||
| 37 | /* There are several places in the buffer where we know | ||
| 38 | the corrspondence: BEG, BEGV, PT, GPT, ZV and Z, | ||
| 39 | and everywhere there is a marker. So we find the one of these places | ||
| 40 | that is closest to the specified position, and scan from there. */ | ||
| 41 | |||
| 42 | /* charpos_to_bytepos returns the byte position corresponding to CHARPOS. */ | ||
| 43 | |||
| 44 | /* This macro is a subroutine of charpos_to_bytepos. | ||
| 45 | Note that it is desirable that BYTEPOS is not evaluated | ||
| 46 | except when we really want its value. */ | ||
| 47 | |||
| 48 | #define CONSIDER(CHARPOS, BYTEPOS) \ | ||
| 49 | { \ | ||
| 50 | int this_charpos = (CHARPOS); \ | ||
| 51 | int changed = 0; \ | ||
| 52 | \ | ||
| 53 | if (this_charpos == charpos) \ | ||
| 54 | return (BYTEPOS); \ | ||
| 55 | else if (this_charpos > charpos) \ | ||
| 56 | { \ | ||
| 57 | if (this_charpos < best_above) \ | ||
| 58 | { \ | ||
| 59 | best_above = this_charpos; \ | ||
| 60 | best_above_byte = (BYTEPOS); \ | ||
| 61 | changed = 1; \ | ||
| 62 | } \ | ||
| 63 | } \ | ||
| 64 | else if (this_charpos > best_below) \ | ||
| 65 | { \ | ||
| 66 | best_below = this_charpos; \ | ||
| 67 | best_below_byte = (BYTEPOS); \ | ||
| 68 | changed = 1; \ | ||
| 69 | } \ | ||
| 70 | \ | ||
| 71 | if (changed) \ | ||
| 72 | { \ | ||
| 73 | if (best_above - best_below == best_above_byte - best_below_byte) \ | ||
| 74 | return best_below_byte + (charpos - best_below); \ | ||
| 75 | } \ | ||
| 76 | } | ||
| 77 | |||
| 78 | int | ||
| 79 | charpos_to_bytepos (charpos) | ||
| 80 | int charpos; | ||
| 81 | { | ||
| 82 | return buf_charpos_to_bytepos (current_buffer, charpos); | ||
| 83 | } | ||
| 84 | |||
| 85 | int | ||
| 86 | buf_charpos_to_bytepos (b, charpos) | ||
| 87 | struct buffer *b; | ||
| 88 | int charpos; | ||
| 89 | { | ||
| 90 | Lisp_Object tail; | ||
| 91 | int gapend_byte = BUF_GPT_BYTE (b) + BUF_GAP_SIZE (b); | ||
| 92 | int best_above, best_above_byte; | ||
| 93 | int best_below, best_below_byte; | ||
| 94 | |||
| 95 | if (charpos < BUF_BEG (b) || charpos > BUF_Z (b)) | ||
| 96 | abort (); | ||
| 97 | |||
| 98 | best_above = BUF_Z (b); | ||
| 99 | best_above_byte = BUF_Z_BYTE (b); | ||
| 100 | |||
| 101 | /* If this buffer has as many characters as bytes, | ||
| 102 | each character must be one byte. | ||
| 103 | This takes care of the case where enable-multibyte-characters is nil. */ | ||
| 104 | if (best_above == best_above_byte) | ||
| 105 | return charpos; | ||
| 106 | |||
| 107 | best_below = 1; | ||
| 108 | best_below_byte = 1; | ||
| 109 | |||
| 110 | /* We find in best_above and best_above_byte | ||
| 111 | the closest known point above CHARPOS, | ||
| 112 | and in best_below and best_below_byte | ||
| 113 | the closest known point below CHARPOS, | ||
| 114 | |||
| 115 | If at any point we can tell that the space between those | ||
| 116 | two best approximations is all single-byte, | ||
| 117 | we interpolate the result immediately. */ | ||
| 118 | |||
| 119 | CONSIDER (BUF_PT (b), BUF_PT_BYTE (b)); | ||
| 120 | CONSIDER (BUF_GPT (b), BUF_GPT_BYTE (b)); | ||
| 121 | CONSIDER (BUF_BEGV (b), BUF_BEGV_BYTE (b)); | ||
| 122 | CONSIDER (BUF_ZV (b), BUF_ZV_BYTE (b)); | ||
| 123 | |||
| 124 | if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff) | ||
| 125 | CONSIDER (cached_charpos, cached_bytepos); | ||
| 126 | |||
| 127 | tail = BUF_MARKERS (b); | ||
| 128 | while (XSYMBOL (tail) != XSYMBOL (Qnil)) | ||
| 129 | { | ||
| 130 | int i = XMARKER (tail)->bufpos; | ||
| 131 | CONSIDER (XMARKER (tail)->charpos, | ||
| 132 | (i > gapend_byte ? i - BUF_GAP_SIZE (b) | ||
| 133 | : i > BUF_GPT_BYTE (b) ? BUF_GPT_BYTE (b) | ||
| 134 | : i)); | ||
| 135 | |||
| 136 | /* If we are down to a range of 50 chars, | ||
| 137 | don't bother checking any other markers; | ||
| 138 | scan the intervening chars directly now. */ | ||
| 139 | if (best_above - best_below < 50) | ||
| 140 | break; | ||
| 141 | |||
| 142 | tail = XMARKER (tail)->chain; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* We get here if we did not exactly hit one of the known places. | ||
| 146 | We have one known above and one known below. | ||
| 147 | Scan, counting characters, from whichever one is closer. */ | ||
| 148 | |||
| 149 | if (charpos - best_below < best_above - charpos) | ||
| 150 | { | ||
| 151 | int record = charpos - best_below > 5000; | ||
| 152 | |||
| 153 | while (best_below != charpos) | ||
| 154 | { | ||
| 155 | best_below++; | ||
| 156 | BUF_INC_POS (b, best_below_byte); | ||
| 157 | } | ||
| 158 | |||
| 159 | /* If this position is quite far from the nearest known position, | ||
| 160 | cache the correspondence by creating a marker here. | ||
| 161 | It will last until the next GC. */ | ||
| 162 | if (record) | ||
| 163 | { | ||
| 164 | Lisp_Object marker; | ||
| 165 | marker = Fmake_marker (); | ||
| 166 | set_marker_both (marker, Qnil, best_below, best_below_byte); | ||
| 167 | } | ||
| 168 | |||
| 169 | cached_buffer = b; | ||
| 170 | cached_modiff = BUF_MODIFF (b); | ||
| 171 | cached_charpos = best_below; | ||
| 172 | cached_bytepos = best_below_byte; | ||
| 173 | |||
| 174 | return best_below_byte; | ||
| 175 | } | ||
| 176 | else | ||
| 177 | { | ||
| 178 | int record = best_above - charpos > 5000; | ||
| 179 | |||
| 180 | while (best_above != charpos) | ||
| 181 | { | ||
| 182 | best_above--; | ||
| 183 | BUF_DEC_POS (b, best_above_byte); | ||
| 184 | } | ||
| 185 | |||
| 186 | /* If this position is quite far from the nearest known position, | ||
| 187 | cache the correspondence by creating a marker here. | ||
| 188 | It will last until the next GC. */ | ||
| 189 | if (record) | ||
| 190 | { | ||
| 191 | Lisp_Object marker; | ||
| 192 | marker = Fmake_marker (); | ||
| 193 | set_marker_both (marker, Qnil, best_above, best_above_byte); | ||
| 194 | } | ||
| 195 | |||
| 196 | cached_buffer = b; | ||
| 197 | cached_modiff = BUF_MODIFF (b); | ||
| 198 | cached_charpos = best_above; | ||
| 199 | cached_bytepos = best_above_byte; | ||
| 200 | |||
| 201 | return best_above_byte; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | #undef CONSIDER | ||
| 206 | |||
| 207 | /* bytepos_to_charpos returns the char position corresponding to BYTEPOS. */ | ||
| 208 | |||
| 209 | /* This macro is a subroutine of bytepos_to_charpos. | ||
| 210 | It is used when BYTEPOS is actually the byte position. */ | ||
| 211 | |||
| 212 | #define CONSIDER(BYTEPOS, CHARPOS) \ | ||
| 213 | { \ | ||
| 214 | int this_bytepos = (BYTEPOS); \ | ||
| 215 | int changed = 0; \ | ||
| 216 | \ | ||
| 217 | if (this_bytepos == bytepos) \ | ||
| 218 | return (CHARPOS); \ | ||
| 219 | else if (this_bytepos > bytepos) \ | ||
| 220 | { \ | ||
| 221 | if (this_bytepos < best_above_byte) \ | ||
| 222 | { \ | ||
| 223 | best_above = (CHARPOS); \ | ||
| 224 | best_above_byte = this_bytepos; \ | ||
| 225 | changed = 1; \ | ||
| 226 | } \ | ||
| 227 | } \ | ||
| 228 | else if (this_bytepos > best_below_byte) \ | ||
| 229 | { \ | ||
| 230 | best_below = (CHARPOS); \ | ||
| 231 | best_below_byte = this_bytepos; \ | ||
| 232 | changed = 1; \ | ||
| 233 | } \ | ||
| 234 | \ | ||
| 235 | if (changed) \ | ||
| 236 | { \ | ||
| 237 | if (best_above - best_below == best_above_byte - best_below_byte) \ | ||
| 238 | return best_below + (bytepos - best_below_byte); \ | ||
| 239 | } \ | ||
| 240 | } | ||
| 241 | |||
| 242 | int | ||
| 243 | bytepos_to_charpos (bytepos) | ||
| 244 | int bytepos; | ||
| 245 | { | ||
| 246 | return buf_bytepos_to_charpos (current_buffer, bytepos); | ||
| 247 | } | ||
| 248 | |||
| 249 | int | ||
| 250 | buf_bytepos_to_charpos (b, bytepos) | ||
| 251 | struct buffer *b; | ||
| 252 | int bytepos; | ||
| 253 | { | ||
| 254 | Lisp_Object tail; | ||
| 255 | int best_above, best_above_byte; | ||
| 256 | int best_below, best_below_byte; | ||
| 257 | |||
| 258 | if (bytepos < BUF_BEG_BYTE (b) || bytepos > BUF_Z_BYTE (b)) | ||
| 259 | abort (); | ||
| 260 | |||
| 261 | best_above = BUF_Z (b); | ||
| 262 | best_above_byte = BUF_Z_BYTE (b); | ||
| 263 | |||
| 264 | /* If this buffer has as many characters as bytes, | ||
| 265 | each character must be one byte. | ||
| 266 | This takes care of the case where enable-multibyte-characters is nil. */ | ||
| 267 | if (best_above == best_above_byte) | ||
| 268 | return bytepos; | ||
| 269 | |||
| 270 | best_below = 1; | ||
| 271 | best_below_byte = 1; | ||
| 272 | |||
| 273 | CONSIDER (BUF_PT_BYTE (b), BUF_PT (b)); | ||
| 274 | CONSIDER (BUF_GPT_BYTE (b), BUF_GPT (b)); | ||
| 275 | CONSIDER (BUF_BEGV_BYTE (b), BUF_BEGV (b)); | ||
| 276 | CONSIDER (BUF_ZV_BYTE (b), BUF_ZV (b)); | ||
| 277 | |||
| 278 | if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff) | ||
| 279 | CONSIDER (cached_bytepos, cached_charpos); | ||
| 280 | |||
| 281 | tail = BUF_MARKERS (b); | ||
| 282 | while (XSYMBOL (tail) != XSYMBOL (Qnil)) | ||
| 283 | { | ||
| 284 | int marker_bytepos = XMARKER (tail)->bufpos; | ||
| 285 | |||
| 286 | if (marker_bytepos > BUF_GPT_BYTE (b) + BUF_GAP_SIZE (b)) | ||
| 287 | marker_bytepos -= BUF_GAP_SIZE (b); | ||
| 288 | else if (marker_bytepos > BUF_GPT_BYTE (b)) | ||
| 289 | marker_bytepos = BUF_GPT_BYTE (b); | ||
| 290 | |||
| 291 | CONSIDER (marker_bytepos, XMARKER (tail)->charpos); | ||
| 292 | |||
| 293 | /* If we are down to a range of 50 chars, | ||
| 294 | don't bother checking any other markers; | ||
| 295 | scan the intervening chars directly now. */ | ||
| 296 | if (best_above - best_below < 50) | ||
| 297 | break; | ||
| 298 | |||
| 299 | tail = XMARKER (tail)->chain; | ||
| 300 | } | ||
| 301 | |||
| 302 | /* We get here if we did not exactly hit one of the known places. | ||
| 303 | We have one known above and one known below. | ||
| 304 | Scan, counting characters, from whichever one is closer. */ | ||
| 305 | |||
| 306 | if (bytepos - best_below_byte < best_above_byte - bytepos) | ||
| 307 | { | ||
| 308 | int record = best_above_byte - bytepos > 5000; | ||
| 309 | |||
| 310 | while (best_below_byte < bytepos) | ||
| 311 | { | ||
| 312 | best_below++; | ||
| 313 | BUF_INC_POS (b, best_below_byte); | ||
| 314 | } | ||
| 315 | |||
| 316 | /* If this position is quite far from the nearest known position, | ||
| 317 | cache the correspondence by creating a marker here. | ||
| 318 | It will last until the next GC. */ | ||
| 319 | if (record) | ||
| 320 | { | ||
| 321 | Lisp_Object marker; | ||
| 322 | marker = Fmake_marker (); | ||
| 323 | set_marker_both (marker, Qnil, best_below, best_below_byte); | ||
| 324 | } | ||
| 325 | |||
| 326 | cached_buffer = b; | ||
| 327 | cached_modiff = BUF_MODIFF (b); | ||
| 328 | cached_charpos = best_below; | ||
| 329 | cached_bytepos = best_below_byte; | ||
| 330 | |||
| 331 | return best_below; | ||
| 332 | } | ||
| 333 | else | ||
| 334 | { | ||
| 335 | int record = best_above_byte - bytepos > 5000; | ||
| 336 | |||
| 337 | while (best_above_byte > bytepos) | ||
| 338 | { | ||
| 339 | best_above--; | ||
| 340 | BUF_DEC_POS (b, best_above_byte); | ||
| 341 | } | ||
| 342 | |||
| 343 | /* If this position is quite far from the nearest known position, | ||
| 344 | cache the correspondence by creating a marker here. | ||
| 345 | It will last until the next GC. */ | ||
| 346 | if (record) | ||
| 347 | { | ||
| 348 | Lisp_Object marker; | ||
| 349 | marker = Fmake_marker (); | ||
| 350 | set_marker_both (marker, Qnil, best_above, best_above_byte); | ||
| 351 | } | ||
| 352 | |||
| 353 | cached_buffer = b; | ||
| 354 | cached_modiff = BUF_MODIFF (b); | ||
| 355 | cached_charpos = best_above; | ||
| 356 | cached_bytepos = best_above_byte; | ||
| 357 | |||
| 358 | return best_above; | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | #undef CONSIDER | ||
| 363 | |||
| 26 | /* Operations on markers. */ | 364 | /* Operations on markers. */ |
| 27 | 365 | ||
| 28 | DEFUN ("marker-buffer", Fmarker_buffer, Smarker_buffer, 1, 1, 0, | 366 | DEFUN ("marker-buffer", Fmarker_buffer, Smarker_buffer, 1, 1, 0, |
| @@ -54,21 +392,8 @@ DEFUN ("marker-position", Fmarker_position, Smarker_position, 1, 1, 0, | |||
| 54 | 392 | ||
| 55 | CHECK_MARKER (marker, 0); | 393 | CHECK_MARKER (marker, 0); |
| 56 | if (XMARKER (marker)->buffer) | 394 | if (XMARKER (marker)->buffer) |
| 57 | { | 395 | return make_number (XMARKER (marker)->charpos); |
| 58 | buf = XMARKER (marker)->buffer; | ||
| 59 | i = XMARKER (marker)->bufpos; | ||
| 60 | 396 | ||
| 61 | if (i > BUF_GPT (buf) + BUF_GAP_SIZE (buf)) | ||
| 62 | i -= BUF_GAP_SIZE (buf); | ||
| 63 | else if (i > BUF_GPT (buf)) | ||
| 64 | i = BUF_GPT (buf); | ||
| 65 | |||
| 66 | if (i < BUF_BEG (buf) || i > BUF_Z (buf)) | ||
| 67 | abort (); | ||
| 68 | |||
| 69 | XSETFASTINT (pos, i); | ||
| 70 | return pos; | ||
| 71 | } | ||
| 72 | return Qnil; | 397 | return Qnil; |
| 73 | } | 398 | } |
| 74 | 399 | ||
| @@ -81,7 +406,7 @@ Returns MARKER.") | |||
| 81 | (marker, position, buffer) | 406 | (marker, position, buffer) |
| 82 | Lisp_Object marker, position, buffer; | 407 | Lisp_Object marker, position, buffer; |
| 83 | { | 408 | { |
| 84 | register int charno; | 409 | register int charno, bytepos; |
| 85 | register struct buffer *b; | 410 | register struct buffer *b; |
| 86 | register struct Lisp_Marker *m; | 411 | register struct Lisp_Marker *m; |
| 87 | 412 | ||
| @@ -95,7 +420,6 @@ Returns MARKER.") | |||
| 95 | return marker; | 420 | return marker; |
| 96 | } | 421 | } |
| 97 | 422 | ||
| 98 | CHECK_NUMBER_COERCE_MARKER (position, 1); | ||
| 99 | if (NILP (buffer)) | 423 | if (NILP (buffer)) |
| 100 | b = current_buffer; | 424 | b = current_buffer; |
| 101 | else | 425 | else |
| @@ -110,15 +434,38 @@ Returns MARKER.") | |||
| 110 | } | 434 | } |
| 111 | } | 435 | } |
| 112 | 436 | ||
| 113 | charno = XINT (position); | ||
| 114 | m = XMARKER (marker); | 437 | m = XMARKER (marker); |
| 115 | 438 | ||
| 439 | /* Optimize the special case where we are copying the position | ||
| 440 | of an existing marker, and MARKER is already in the same buffer. */ | ||
| 441 | if (MARKERP (position) && b == XMARKER (position)->buffer | ||
| 442 | && b == m->buffer) | ||
| 443 | { | ||
| 444 | m->bufpos = XMARKER (position)->bufpos; | ||
| 445 | m->charpos = XMARKER (position)->charpos; | ||
| 446 | return marker; | ||
| 447 | } | ||
| 448 | |||
| 449 | CHECK_NUMBER_COERCE_MARKER (position, 1); | ||
| 450 | |||
| 451 | charno = XINT (position); | ||
| 452 | |||
| 116 | if (charno < BUF_BEG (b)) | 453 | if (charno < BUF_BEG (b)) |
| 117 | charno = BUF_BEG (b); | 454 | charno = BUF_BEG (b); |
| 118 | if (charno > BUF_Z (b)) | 455 | if (charno > BUF_Z (b)) |
| 119 | charno = BUF_Z (b); | 456 | charno = BUF_Z (b); |
| 120 | if (charno > BUF_GPT (b)) charno += BUF_GAP_SIZE (b); | 457 | |
| 121 | m->bufpos = charno; | 458 | bytepos = buf_charpos_to_bytepos (b, charno); |
| 459 | |||
| 460 | /* Every character is at least one byte. */ | ||
| 461 | if (charno > bytepos) | ||
| 462 | abort (); | ||
| 463 | |||
| 464 | if (bytepos > BUF_GPT_BYTE (b)) | ||
| 465 | bytepos += BUF_GAP_SIZE (b); | ||
| 466 | |||
| 467 | m->bufpos = bytepos; | ||
| 468 | m->charpos = charno; | ||
| 122 | 469 | ||
| 123 | if (m->buffer != b) | 470 | if (m->buffer != b) |
| 124 | { | 471 | { |
| @@ -138,21 +485,20 @@ Lisp_Object | |||
| 138 | set_marker_restricted (marker, pos, buffer) | 485 | set_marker_restricted (marker, pos, buffer) |
| 139 | Lisp_Object marker, pos, buffer; | 486 | Lisp_Object marker, pos, buffer; |
| 140 | { | 487 | { |
| 141 | register int charno; | 488 | register int charno, bytepos; |
| 142 | register struct buffer *b; | 489 | register struct buffer *b; |
| 143 | register struct Lisp_Marker *m; | 490 | register struct Lisp_Marker *m; |
| 144 | 491 | ||
| 145 | CHECK_MARKER (marker, 0); | 492 | CHECK_MARKER (marker, 0); |
| 146 | /* If position is nil or a marker that points nowhere, | 493 | /* If position is nil or a marker that points nowhere, |
| 147 | make this marker point nowhere. */ | 494 | make this marker point nowhere. */ |
| 148 | if (NILP (pos) || | 495 | if (NILP (pos) |
| 149 | (MARKERP (pos) && !XMARKER (pos)->buffer)) | 496 | || (MARKERP (pos) && !XMARKER (pos)->buffer)) |
| 150 | { | 497 | { |
| 151 | unchain_marker (marker); | 498 | unchain_marker (marker); |
| 152 | return marker; | 499 | return marker; |
| 153 | } | 500 | } |
| 154 | 501 | ||
| 155 | CHECK_NUMBER_COERCE_MARKER (pos, 1); | ||
| 156 | if (NILP (buffer)) | 502 | if (NILP (buffer)) |
| 157 | b = current_buffer; | 503 | b = current_buffer; |
| 158 | else | 504 | else |
| @@ -167,16 +513,38 @@ set_marker_restricted (marker, pos, buffer) | |||
| 167 | } | 513 | } |
| 168 | } | 514 | } |
| 169 | 515 | ||
| 170 | charno = XINT (pos); | ||
| 171 | m = XMARKER (marker); | 516 | m = XMARKER (marker); |
| 172 | 517 | ||
| 518 | /* Optimize the special case where we are copying the position | ||
| 519 | of an existing marker, and MARKER is already in the same buffer. */ | ||
| 520 | if (MARKERP (pos) && b == XMARKER (pos)->buffer | ||
| 521 | && b == m->buffer) | ||
| 522 | { | ||
| 523 | m->bufpos = XMARKER (pos)->bufpos; | ||
| 524 | m->charpos = XMARKER (pos)->charpos; | ||
| 525 | return marker; | ||
| 526 | } | ||
| 527 | |||
| 528 | CHECK_NUMBER_COERCE_MARKER (pos, 1); | ||
| 529 | |||
| 530 | charno = XINT (pos); | ||
| 531 | |||
| 173 | if (charno < BUF_BEGV (b)) | 532 | if (charno < BUF_BEGV (b)) |
| 174 | charno = BUF_BEGV (b); | 533 | charno = BUF_BEGV (b); |
| 175 | if (charno > BUF_ZV (b)) | 534 | if (charno > BUF_ZV (b)) |
| 176 | charno = BUF_ZV (b); | 535 | charno = BUF_ZV (b); |
| 177 | if (charno > BUF_GPT (b)) | 536 | |
| 178 | charno += BUF_GAP_SIZE (b); | 537 | bytepos = buf_charpos_to_bytepos (b, charno); |
| 179 | m->bufpos = charno; | 538 | |
| 539 | /* Every character is at least one byte. */ | ||
| 540 | if (charno > bytepos) | ||
| 541 | abort (); | ||
| 542 | |||
| 543 | if (bytepos > BUF_GPT_BYTE (b)) | ||
| 544 | bytepos += BUF_GAP_SIZE (b); | ||
| 545 | |||
| 546 | m->bufpos = bytepos; | ||
| 547 | m->charpos = charno; | ||
| 180 | 548 | ||
| 181 | if (m->buffer != b) | 549 | if (m->buffer != b) |
| 182 | { | 550 | { |
| @@ -188,7 +556,133 @@ set_marker_restricted (marker, pos, buffer) | |||
| 188 | 556 | ||
| 189 | return marker; | 557 | return marker; |
| 190 | } | 558 | } |
| 559 | |||
| 560 | /* Set the position of MARKER, specifying both the | ||
| 561 | character position and the corresponding byte position. */ | ||
| 191 | 562 | ||
| 563 | Lisp_Object | ||
| 564 | set_marker_both (marker, buffer, charpos, bytepos) | ||
| 565 | Lisp_Object marker, buffer; | ||
| 566 | int charpos, bytepos; | ||
| 567 | { | ||
| 568 | register struct buffer *b; | ||
| 569 | register struct Lisp_Marker *m; | ||
| 570 | |||
| 571 | CHECK_MARKER (marker, 0); | ||
| 572 | /* If position is nil or a marker that points nowhere, | ||
| 573 | make this marker point nowhere. */ | ||
| 574 | if (NILP (charpos) | ||
| 575 | || (MARKERP (charpos) && !XMARKER (charpos)->buffer)) | ||
| 576 | { | ||
| 577 | unchain_marker (marker); | ||
| 578 | return marker; | ||
| 579 | } | ||
| 580 | |||
| 581 | CHECK_NUMBER_COERCE_MARKER (charpos, 1); | ||
| 582 | if (NILP (buffer)) | ||
| 583 | b = current_buffer; | ||
| 584 | else | ||
| 585 | { | ||
| 586 | CHECK_BUFFER (buffer, 1); | ||
| 587 | b = XBUFFER (buffer); | ||
| 588 | /* If buffer is dead, set marker to point nowhere. */ | ||
| 589 | if (EQ (b->name, Qnil)) | ||
| 590 | { | ||
| 591 | unchain_marker (marker); | ||
| 592 | return marker; | ||
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | m = XMARKER (marker); | ||
| 597 | |||
| 598 | /* In a single-byte buffer, the two positions must be equal. */ | ||
| 599 | if (BUF_Z (b) == BUF_Z_BYTE (b) | ||
| 600 | && charpos != bytepos) | ||
| 601 | abort (); | ||
| 602 | /* Every character is at least one byte. */ | ||
| 603 | if (charpos > bytepos) | ||
| 604 | abort (); | ||
| 605 | |||
| 606 | if (bytepos > BUF_GPT_BYTE (b)) | ||
| 607 | bytepos += BUF_GAP_SIZE (b); | ||
| 608 | |||
| 609 | m->bufpos = bytepos; | ||
| 610 | m->charpos = charpos; | ||
| 611 | |||
| 612 | if (m->buffer != b) | ||
| 613 | { | ||
| 614 | unchain_marker (marker); | ||
| 615 | m->buffer = b; | ||
| 616 | m->chain = BUF_MARKERS (b); | ||
| 617 | BUF_MARKERS (b) = marker; | ||
| 618 | } | ||
| 619 | |||
| 620 | return marker; | ||
| 621 | } | ||
| 622 | |||
| 623 | /* This version of set_marker_both won't let the position | ||
| 624 | be outside the visible part. */ | ||
| 625 | |||
| 626 | Lisp_Object | ||
| 627 | set_marker_restricted_both (marker, buffer, charpos, bytepos) | ||
| 628 | Lisp_Object marker, buffer; | ||
| 629 | int charpos, bytepos; | ||
| 630 | { | ||
| 631 | register struct buffer *b; | ||
| 632 | register struct Lisp_Marker *m; | ||
| 633 | |||
| 634 | CHECK_MARKER (marker, 0); | ||
| 635 | |||
| 636 | if (NILP (buffer)) | ||
| 637 | b = current_buffer; | ||
| 638 | else | ||
| 639 | { | ||
| 640 | CHECK_BUFFER (buffer, 1); | ||
| 641 | b = XBUFFER (buffer); | ||
| 642 | /* If buffer is dead, set marker to point nowhere. */ | ||
| 643 | if (EQ (b->name, Qnil)) | ||
| 644 | { | ||
| 645 | unchain_marker (marker); | ||
| 646 | return marker; | ||
| 647 | } | ||
| 648 | } | ||
| 649 | |||
| 650 | m = XMARKER (marker); | ||
| 651 | |||
| 652 | if (charpos < BUF_BEGV (b)) | ||
| 653 | charpos = BUF_BEGV (b); | ||
| 654 | if (charpos > BUF_ZV (b)) | ||
| 655 | charpos = BUF_ZV (b); | ||
| 656 | if (bytepos < BUF_BEGV_BYTE (b)) | ||
| 657 | bytepos = BUF_BEGV_BYTE (b); | ||
| 658 | if (bytepos > BUF_ZV_BYTE (b)) | ||
| 659 | bytepos = BUF_ZV_BYTE (b); | ||
| 660 | |||
| 661 | /* In a single-byte buffer, the two positions must be equal. */ | ||
| 662 | if (BUF_Z (b) == BUF_Z_BYTE (b) | ||
| 663 | && charpos != bytepos) | ||
| 664 | abort (); | ||
| 665 | /* Every character is at least one byte. */ | ||
| 666 | if (charpos > bytepos) | ||
| 667 | abort (); | ||
| 668 | |||
| 669 | if (bytepos > BUF_GPT_BYTE (b)) | ||
| 670 | bytepos += BUF_GAP_SIZE (b); | ||
| 671 | |||
| 672 | m->bufpos = bytepos; | ||
| 673 | m->charpos = charpos; | ||
| 674 | |||
| 675 | if (m->buffer != b) | ||
| 676 | { | ||
| 677 | unchain_marker (marker); | ||
| 678 | m->buffer = b; | ||
| 679 | m->chain = BUF_MARKERS (b); | ||
| 680 | BUF_MARKERS (b) = marker; | ||
| 681 | } | ||
| 682 | |||
| 683 | return marker; | ||
| 684 | } | ||
| 685 | |||
| 192 | /* This is called during garbage collection, | 686 | /* This is called during garbage collection, |
| 193 | so we must be careful to ignore and preserve mark bits, | 687 | so we must be careful to ignore and preserve mark bits, |
| 194 | including those in chain fields of markers. */ | 688 | including those in chain fields of markers. */ |
| @@ -242,7 +736,7 @@ unchain_marker (marker) | |||
| 242 | XMARKER (marker)->buffer = 0; | 736 | XMARKER (marker)->buffer = 0; |
| 243 | } | 737 | } |
| 244 | 738 | ||
| 245 | /* Return the buffer position of marker MARKER, as a C integer. */ | 739 | /* Return the char position of marker MARKER, as a C integer. */ |
| 246 | 740 | ||
| 247 | int | 741 | int |
| 248 | marker_position (marker) | 742 | marker_position (marker) |
| @@ -250,17 +744,32 @@ marker_position (marker) | |||
| 250 | { | 744 | { |
| 251 | register struct Lisp_Marker *m = XMARKER (marker); | 745 | register struct Lisp_Marker *m = XMARKER (marker); |
| 252 | register struct buffer *buf = m->buffer; | 746 | register struct buffer *buf = m->buffer; |
| 747 | |||
| 748 | if (!buf) | ||
| 749 | error ("Marker does not point anywhere"); | ||
| 750 | |||
| 751 | return m->charpos; | ||
| 752 | } | ||
| 753 | |||
| 754 | /* Return the byte position of marker MARKER, as a C integer. */ | ||
| 755 | |||
| 756 | int | ||
| 757 | marker_byte_position (marker) | ||
| 758 | Lisp_Object marker; | ||
| 759 | { | ||
| 760 | register struct Lisp_Marker *m = XMARKER (marker); | ||
| 761 | register struct buffer *buf = m->buffer; | ||
| 253 | register int i = m->bufpos; | 762 | register int i = m->bufpos; |
| 254 | 763 | ||
| 255 | if (!buf) | 764 | if (!buf) |
| 256 | error ("Marker does not point anywhere"); | 765 | error ("Marker does not point anywhere"); |
| 257 | 766 | ||
| 258 | if (i > BUF_GPT (buf) + BUF_GAP_SIZE (buf)) | 767 | if (i > BUF_GPT_BYTE (buf) + BUF_GAP_SIZE (buf)) |
| 259 | i -= BUF_GAP_SIZE (buf); | 768 | i -= BUF_GAP_SIZE (buf); |
| 260 | else if (i > BUF_GPT (buf)) | 769 | else if (i > BUF_GPT_BYTE (buf)) |
| 261 | i = BUF_GPT (buf); | 770 | i = BUF_GPT_BYTE (buf); |
| 262 | 771 | ||
| 263 | if (i < BUF_BEG (buf) || i > BUF_Z (buf)) | 772 | if (i < BUF_BEG_BYTE (buf) || i > BUF_Z_BYTE (buf)) |
| 264 | abort (); | 773 | abort (); |
| 265 | 774 | ||
| 266 | return i; | 775 | return i; |
| @@ -317,7 +826,7 @@ If TYPE is nil, it means the marker stays behind when you insert text at it.") | |||
| 317 | 826 | ||
| 318 | DEFUN ("buffer-has-markers-at", Fbuffer_has_markers_at, Sbuffer_has_markers_at, | 827 | DEFUN ("buffer-has-markers-at", Fbuffer_has_markers_at, Sbuffer_has_markers_at, |
| 319 | 1, 1, 0, | 828 | 1, 1, 0, |
| 320 | "Return t if there are markers pointing at POSITION in the currentbuffer.") | 829 | "Return t if there are markers pointing at POSITION in the current buffer.") |
| 321 | (position) | 830 | (position) |
| 322 | Lisp_Object position; | 831 | Lisp_Object position; |
| 323 | { | 832 | { |
| @@ -330,12 +839,11 @@ DEFUN ("buffer-has-markers-at", Fbuffer_has_markers_at, Sbuffer_has_markers_at, | |||
| 330 | charno = BEG; | 839 | charno = BEG; |
| 331 | if (charno > Z) | 840 | if (charno > Z) |
| 332 | charno = Z; | 841 | charno = Z; |
| 333 | if (charno > GPT) charno += GAP_SIZE; | ||
| 334 | 842 | ||
| 335 | for (tail = BUF_MARKERS (current_buffer); | 843 | for (tail = BUF_MARKERS (current_buffer); |
| 336 | XSYMBOL (tail) != XSYMBOL (Qnil); | 844 | XSYMBOL (tail) != XSYMBOL (Qnil); |
| 337 | tail = XMARKER (tail)->chain) | 845 | tail = XMARKER (tail)->chain) |
| 338 | if (XMARKER (tail)->bufpos == charno) | 846 | if (XMARKER (tail)->charpos == charno) |
| 339 | return Qt; | 847 | return Qt; |
| 340 | 848 | ||
| 341 | return Qnil; | 849 | return Qnil; |