diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/undo.c | 123 |
1 files changed, 72 insertions, 51 deletions
diff --git a/src/undo.c b/src/undo.c index 21f24b3c156..b966ab3e79b 100644 --- a/src/undo.c +++ b/src/undo.c | |||
| @@ -89,6 +89,12 @@ record_delete (beg, length) | |||
| 89 | XFASTINT (sbeg) = beg; | 89 | XFASTINT (sbeg) = beg; |
| 90 | XFASTINT (lbeg) = beg; | 90 | XFASTINT (lbeg) = beg; |
| 91 | XFASTINT (lend) = beg + length; | 91 | XFASTINT (lend) = beg + length; |
| 92 | |||
| 93 | /* If point isn't at start of deleted range, record where it is. */ | ||
| 94 | if (PT != sbeg) | ||
| 95 | current_buffer->undo_list | ||
| 96 | = Fcons (make_number (PT), current_buffer->undo_list); | ||
| 97 | |||
| 92 | current_buffer->undo_list | 98 | current_buffer->undo_list |
| 93 | = Fcons (Fcons (Fbuffer_substring (lbeg, lend), sbeg), | 99 | = Fcons (Fcons (Fbuffer_substring (lbeg, lend), sbeg), |
| 94 | current_buffer->undo_list); | 100 | current_buffer->undo_list); |
| @@ -258,66 +264,81 @@ Return what remains of the list.") | |||
| 258 | { | 264 | { |
| 259 | while (1) | 265 | while (1) |
| 260 | { | 266 | { |
| 261 | Lisp_Object next, car, cdr; | 267 | Lisp_Object next; |
| 262 | next = Fcar (list); | 268 | next = Fcar (list); |
| 263 | list = Fcdr (list); | 269 | list = Fcdr (list); |
| 270 | /* Exit inner loop at undo boundary. */ | ||
| 264 | if (NILP (next)) | 271 | if (NILP (next)) |
| 265 | break; | 272 | break; |
| 266 | car = Fcar (next); | 273 | /* Handle an integer by setting point to that value. */ |
| 267 | cdr = Fcdr (next); | 274 | if (XTYPE (next) == Lisp_Int) |
| 268 | if (EQ (car, Qt)) | 275 | SET_PT (clip_to_bounds (BEGV, XINT (next), ZV)); |
| 269 | { | 276 | else if (XTYPE (next) == Lisp_Cons) |
| 270 | Lisp_Object high, low; | ||
| 271 | int mod_time; | ||
| 272 | high = Fcar (cdr); | ||
| 273 | low = Fcdr (cdr); | ||
| 274 | mod_time = (high << 16) + low; | ||
| 275 | /* If this records an obsolete save | ||
| 276 | (not matching the actual disk file) | ||
| 277 | then don't mark unmodified. */ | ||
| 278 | if (mod_time != current_buffer->modtime) | ||
| 279 | break; | ||
| 280 | #ifdef CLASH_DETECTION | ||
| 281 | Funlock_buffer (); | ||
| 282 | #endif /* CLASH_DETECTION */ | ||
| 283 | Fset_buffer_modified_p (Qnil); | ||
| 284 | } | ||
| 285 | else if (XTYPE (car) == Lisp_Int && XTYPE (cdr) == Lisp_Int) | ||
| 286 | { | ||
| 287 | Lisp_Object end; | ||
| 288 | if (XINT (car) < BEGV | ||
| 289 | || XINT (cdr) > ZV) | ||
| 290 | error ("Changes to be undone are outside visible portion of buffer"); | ||
| 291 | Fdelete_region (car, cdr); | ||
| 292 | Fgoto_char (car); | ||
| 293 | } | ||
| 294 | else if (XTYPE (car) == Lisp_String && XTYPE (cdr) == Lisp_Int) | ||
| 295 | { | 277 | { |
| 296 | Lisp_Object membuf; | 278 | Lisp_Object car, cdr; |
| 297 | int pos = XINT (cdr); | 279 | |
| 298 | membuf = car; | 280 | car = Fcar (next); |
| 299 | if (pos < 0) | 281 | cdr = Fcdr (next); |
| 282 | if (EQ (car, Qt)) | ||
| 300 | { | 283 | { |
| 301 | if (-pos < BEGV || -pos > ZV) | 284 | /* Element (t high . low) records previous modtime. */ |
| 302 | error ("Changes to be undone are outside visible portion of buffer"); | 285 | Lisp_Object high, low; |
| 303 | SET_PT (-pos); | 286 | int mod_time; |
| 304 | Finsert (1, &membuf); | 287 | |
| 288 | high = Fcar (cdr); | ||
| 289 | low = Fcdr (cdr); | ||
| 290 | mod_time = (high << 16) + low; | ||
| 291 | /* If this records an obsolete save | ||
| 292 | (not matching the actual disk file) | ||
| 293 | then don't mark unmodified. */ | ||
| 294 | if (mod_time != current_buffer->modtime) | ||
| 295 | break; | ||
| 296 | #ifdef CLASH_DETECTION | ||
| 297 | Funlock_buffer (); | ||
| 298 | #endif /* CLASH_DETECTION */ | ||
| 299 | Fset_buffer_modified_p (Qnil); | ||
| 305 | } | 300 | } |
| 306 | else | 301 | else if (XTYPE (car) == Lisp_Int && XTYPE (cdr) == Lisp_Int) |
| 307 | { | 302 | { |
| 308 | if (pos < BEGV || pos > ZV) | 303 | /* Element (BEG . END) means range was inserted. */ |
| 304 | Lisp_Object end; | ||
| 305 | |||
| 306 | if (XINT (car) < BEGV | ||
| 307 | || XINT (cdr) > ZV) | ||
| 309 | error ("Changes to be undone are outside visible portion of buffer"); | 308 | error ("Changes to be undone are outside visible portion of buffer"); |
| 310 | SET_PT (pos); | 309 | Fdelete_region (car, cdr); |
| 311 | 310 | Fgoto_char (car); | |
| 312 | /* Insert before markers so that if the mark is | 311 | } |
| 313 | currently on the boundary of this deletion, it | 312 | else if (XTYPE (car) == Lisp_String && XTYPE (cdr) == Lisp_Int) |
| 314 | ends up on the other side of the now-undeleted | 313 | { |
| 315 | text from point. Since undo doesn't even keep | 314 | /* Element (STRING . POS) means STRING was deleted. */ |
| 316 | track of the mark, this isn't really necessary, | 315 | Lisp_Object membuf; |
| 317 | but it may lead to better behavior in certain | 316 | int pos = XINT (cdr); |
| 318 | situations. */ | 317 | |
| 319 | Finsert_before_markers (1, &membuf); | 318 | membuf = car; |
| 320 | SET_PT (pos); | 319 | if (pos < 0) |
| 320 | { | ||
| 321 | if (-pos < BEGV || -pos > ZV) | ||
| 322 | error ("Changes to be undone are outside visible portion of buffer"); | ||
| 323 | SET_PT (-pos); | ||
| 324 | Finsert (1, &membuf); | ||
| 325 | } | ||
| 326 | else | ||
| 327 | { | ||
| 328 | if (pos < BEGV || pos > ZV) | ||
| 329 | error ("Changes to be undone are outside visible portion of buffer"); | ||
| 330 | SET_PT (pos); | ||
| 331 | |||
| 332 | /* Insert before markers so that if the mark is | ||
| 333 | currently on the boundary of this deletion, it | ||
| 334 | ends up on the other side of the now-undeleted | ||
| 335 | text from point. Since undo doesn't even keep | ||
| 336 | track of the mark, this isn't really necessary, | ||
| 337 | but it may lead to better behavior in certain | ||
| 338 | situations. */ | ||
| 339 | Finsert_before_markers (1, &membuf); | ||
| 340 | SET_PT (pos); | ||
| 341 | } | ||
| 321 | } | 342 | } |
| 322 | } | 343 | } |
| 323 | } | 344 | } |