1 /* vi:set ts=8 sts=4 sw=4: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* for debugging */ 11 /* #define CHECK(c, s) if (c) EMSG(s) */ 12 #define CHECK(c, s) 13 14 /* 15 * memline.c: Contains the functions for appending, deleting and changing the 16 * text lines. The memfile functions are used to store the information in blocks 17 * of memory, backed up by a file. The structure of the information is a tree. 18 * The root of the tree is a pointer block. The leaves of the tree are data 19 * blocks. In between may be several layers of pointer blocks, forming branches. 20 * 21 * Three types of blocks are used: 22 * - Block nr 0 contains information for recovery 23 * - Pointer blocks contain list of pointers to other blocks. 24 * - Data blocks contain the actual text. 25 * 26 * Block nr 0 contains the block0 structure (see below). 27 * 28 * Block nr 1 is the first pointer block. It is the root of the tree. 29 * Other pointer blocks are branches. 30 * 31 * If a line is too big to fit in a single page, the block containing that 32 * line is made big enough to hold the line. It may span several pages. 33 * Otherwise all blocks are one page. 34 * 35 * A data block that was filled when starting to edit a file and was not 36 * changed since then, can have a negative block number. This means that it 37 * has not yet been assigned a place in the file. When recovering, the lines 38 * in this data block can be read from the original file. When the block is 39 * changed (lines appended/deleted/changed) or when it is flushed it gets a 40 * positive number. Use mf_trans_del() to get the new number, before calling 41 * mf_get(). 42 */ 43 44 #if defined(MSDOS) || defined(WIN32) || defined(_WIN64) 45 # include <io.h> 46 #endif 47 48 #include "vim.h" 49 50 #ifdef HAVE_FCNTL_H 51 # include <fcntl.h> 52 #endif 53 #ifndef UNIX /* it's in os_unix.h for Unix */ 54 # include <time.h> 55 #endif 56 57 #ifdef SASC 58 # include <proto/dos.h> /* for Open() and Close() */ 59 #endif 60 61 typedef struct block0 ZERO_BL; /* contents of the first block */ 62 typedef struct pointer_block PTR_BL; /* contents of a pointer block */ 63 typedef struct data_block DATA_BL; /* contents of a data block */ 64 typedef struct pointer_entry PTR_EN; /* block/line-count pair */ 65 66 #define DATA_ID (('d' << 8) + 'a') /* data block id */ 67 #define PTR_ID (('p' << 8) + 't') /* pointer block id */ 68 #define BLOCK0_ID0 'b' /* block 0 id 0 */ 69 #define BLOCK0_ID1 '0' /* block 0 id 1 */ 70 71 /* 72 * pointer to a block, used in a pointer block 73 */ 74 struct pointer_entry 75 { 76 blocknr_T pe_bnum; /* block number */ 77 linenr_T pe_line_count; /* number of lines in this branch */ 78 linenr_T pe_old_lnum; /* lnum for this block (for recovery) */ 79 int pe_page_count; /* number of pages in block pe_bnum */ 80 }; 81 82 /* 83 * A pointer block contains a list of branches in the tree. 84 */ 85 struct pointer_block 86 { 87 short_u pb_id; /* ID for pointer block: PTR_ID */ 88 short_u pb_count; /* number of pointer in this block */ 89 short_u pb_count_max; /* maximum value for pb_count */ 90 PTR_EN pb_pointer[1]; /* list of pointers to blocks (actually longer) 91 * followed by empty space until end of page */ 92 }; 93 94 /* 95 * A data block is a leaf in the tree. 96 * 97 * The text of the lines is at the end of the block. The text of the first line 98 * in the block is put at the end, the text of the second line in front of it, 99 * etc. Thus the order of the lines is the opposite of the line number. 100 */ 101 struct data_block 102 { 103 short_u db_id; /* ID for data block: DATA_ID */ 104 unsigned db_free; /* free space available */ 105 unsigned db_txt_start; /* byte where text starts */ 106 unsigned db_txt_end; /* byte just after data block */ 107 linenr_T db_line_count; /* number of lines in this block */ 108 unsigned db_index[1]; /* index for start of line (actually bigger) 109 * followed by empty space upto db_txt_start 110 * followed by the text in the lines until 111 * end of page */ 112 }; 113 114 /* 115 * The low bits of db_index hold the actual index. The topmost bit is 116 * used for the global command to be able to mark a line. 117 * This method is not clean, but otherwise there would be at least one extra 118 * byte used for each line. 119 * The mark has to be in this place to keep it with the correct line when other 120 * lines are inserted or deleted. 121 */ 122 #define DB_MARKED ((unsigned)1 << ((sizeof(unsigned) * 8) - 1)) 123 #define DB_INDEX_MASK (~DB_MARKED) 124 125 #define INDEX_SIZE (sizeof(unsigned)) /* size of one db_index entry */ 126 #define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE) /* size of data block header */ 127 128 #define B0_FNAME_SIZE 900 129 #define B0_UNAME_SIZE 40 130 #define B0_HNAME_SIZE 40 131 /* 132 * Restrict the numbers to 32 bits, otherwise most compilers will complain. 133 * This won't detect a 64 bit machine that only swaps a byte in the top 32 134 * bits, but that is crazy anyway. 135 */ 136 #define B0_MAGIC_LONG 0x30313233L 137 #define B0_MAGIC_INT 0x20212223L 138 #define B0_MAGIC_SHORT 0x10111213L 139 #define B0_MAGIC_CHAR 0x55 140 141 /* 142 * Block zero holds all info about the swap file. 143 * 144 * NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing 145 * swap files unusable! 146 * 147 * If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in vim.h!! 148 * 149 * This block is built up of single bytes, to make it portable accros 150 * different machines. b0_magic_* is used to check the byte order and size of 151 * variables, because the rest of the swap file is not portable. 152 */ 153 struct block0 154 { 155 char_u b0_id[2]; /* id for block 0: BLOCK0_ID0 and BLOCK0_ID1 */ 156 char_u b0_version[10]; /* Vim version string */ 157 char_u b0_page_size[4];/* number of bytes per page */ 158 char_u b0_mtime[4]; /* last modification time of file */ 159 char_u b0_ino[4]; /* inode of b0_fname */ 160 char_u b0_pid[4]; /* process id of creator (or 0) */ 161 char_u b0_uname[B0_UNAME_SIZE]; /* name of user (uid if no name) */ 162 char_u b0_hname[B0_HNAME_SIZE]; /* host name (if it has a name) */ 163 char_u b0_fname[B0_FNAME_SIZE]; /* name of file being edited */ 164 long b0_magic_long; /* check for byte order of long */ 165 int b0_magic_int; /* check for byte order of int */ 166 short b0_magic_short; /* check for byte order of short */ 167 char_u b0_magic_char; /* check for last char */ 168 }; 169 #define b0_dirty b0_fname[B0_FNAME_SIZE-1] 170 171 #define STACK_INCR 5 /* nr of entries added to ml_stack at a time */ 172 173 /* 174 * The line number where the first mark may be is remembered. 175 * If it is 0 there are no marks at all. 176 * (always used for the current buffer only, no buffer change possible while 177 * executing a global command). 178 */ 179 static linenr_T lowest_marked = 0; 180 181 /* 182 * arguments for ml_find_line() 183 */ 184 #define ML_DELETE 0x11 /* delete line */ 185 #define ML_INSERT 0x12 /* insert line */ 186 #define ML_FIND 0x13 /* just find the line */ 187 #define ML_FLUSH 0x02 /* flush locked block */ 188 #define ML_SIMPLE(x) (x & 0x10) /* DEL, INS or FIND */ 189 190 static void set_b0_fname __ARGS((ZERO_BL *, buf_T *buf)); 191 static time_t swapfile_info __ARGS((char_u *)); 192 static int recov_file_names __ARGS((char_u **, char_u *, int prepend_dot)); 193 static int ml_append_int __ARGS((buf_T *, linenr_T, char_u *, colnr_T, int, int)); 194 static int ml_delete_int __ARGS((buf_T *, linenr_T, int)); 195 static char_u *findswapname __ARGS((buf_T *, char_u **, char_u *)); 196 static void ml_flush_line __ARGS((buf_T *)); 197 static bhdr_T *ml_new_data __ARGS((memfile_T *, int, int)); 198 static bhdr_T *ml_new_ptr __ARGS((memfile_T *)); 199 static bhdr_T *ml_find_line __ARGS((buf_T *, linenr_T, int)); 200 static int ml_add_stack __ARGS((buf_T *)); 201 static char_u *makeswapname __ARGS((buf_T *, char_u *)); 202 static void ml_lineadd __ARGS((buf_T *, int)); 203 static int b0_magic_wrong __ARGS((ZERO_BL *)); 204 #ifdef CHECK_INODE 205 static int fnamecmp_ino __ARGS((char_u *, char_u *, long)); 206 #endif 207 static void long_to_char __ARGS((long, char_u *)); 208 static long char_to_long __ARGS((char_u *)); 209 #if defined(UNIX) || defined(WIN3264) 210 static char_u *make_percent_swname __ARGS((char_u *dir, char_u *name)); 211 #endif 212 #ifdef FEAT_BYTEOFF 213 static void ml_updatechunk __ARGS((buf_T *buf, long line, long len, int updtype)); 214 #endif 215 216 /* 217 * open a new memline for 'curbuf' 218 * 219 * return FAIL for failure, OK otherwise 220 */ 221 int 222 ml_open() 223 { 224 memfile_T *mfp; 225 bhdr_T *hp = NULL; 226 ZERO_BL *b0p; 227 PTR_BL *pp; 228 DATA_BL *dp; 229 230 /* 231 * init fields in memline struct 232 */ 233 curbuf->b_ml.ml_stack_size = 0; /* no stack yet */ 234 curbuf->b_ml.ml_stack = NULL; /* no stack yet */ 235 curbuf->b_ml.ml_stack_top = 0; /* nothing in the stack */ 236 curbuf->b_ml.ml_locked = NULL; /* no cached block */ 237 curbuf->b_ml.ml_line_lnum = 0; /* no cached line */ 238 #ifdef FEAT_BYTEOFF 239 curbuf->b_ml.ml_chunksize = NULL; 240 #endif 241 242 /* 243 * When 'updatecount' is non-zero, flag that a swap file may be opened later. 244 */ 245 if (p_uc && curbuf->b_p_swf) 246 curbuf->b_may_swap = TRUE; 247 else 248 curbuf->b_may_swap = FALSE; 249 250 /* 251 * Open the memfile. No swap file is created yet. 252 */ 253 mfp = mf_open(NULL, 0); 254 if (mfp == NULL) 255 goto error; 256 257 curbuf->b_ml.ml_mfp = mfp; 258 curbuf->b_ml.ml_flags = ML_EMPTY; 259 curbuf->b_ml.ml_line_count = 1; 260 261 #if defined(MSDOS) && !defined(DJGPP) 262 /* for 16 bit MS-DOS create a swapfile now, because we run out of 263 * memory very quickly */ 264 if (p_uc != 0) 265 ml_open_file(curbuf); 266 #endif 267 268 /* 269 * fill block0 struct and write page 0 270 */ 271 if ((hp = mf_new(mfp, FALSE, 1)) == NULL) 272 goto error; 273 if (hp->bh_bnum != 0) 274 { 275 EMSG(_("E298: Didn't get block nr 0?")); 276 goto error; 277 } 278 b0p = (ZERO_BL *)(hp->bh_data); 279 280 b0p->b0_id[0] = BLOCK0_ID0; 281 b0p->b0_id[1] = BLOCK0_ID1; 282 b0p->b0_dirty = curbuf->b_changed ? 0x55 : 0; 283 b0p->b0_magic_long = (long)B0_MAGIC_LONG; 284 b0p->b0_magic_int = (int)B0_MAGIC_INT; 285 b0p->b0_magic_short = (short)B0_MAGIC_SHORT; 286 b0p->b0_magic_char = B0_MAGIC_CHAR; 287 288 STRNCPY(b0p->b0_version, "VIM ", 4); 289 STRNCPY(b0p->b0_version + 4, Version, 6); 290 set_b0_fname(b0p, curbuf); 291 long_to_char((long)mfp->mf_page_size, b0p->b0_page_size); 292 (void)get_user_name(b0p->b0_uname, B0_UNAME_SIZE); 293 b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL; 294 mch_get_host_name(b0p->b0_hname, B0_HNAME_SIZE); 295 b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL; 296 long_to_char(mch_get_pid(), b0p->b0_pid); 297 298 /* 299 * Always sync block number 0 to disk, so we can check the file name in 300 * the swap file in findswapname(). Don't do this for help files though. 301 * Only works when there's a swapfile, otherwise it's done when the file 302 * is created. 303 */ 304 mf_put(mfp, hp, TRUE, FALSE); 305 if (!curbuf->b_help) 306 (void)mf_sync(mfp, 0); 307 308 /* 309 * fill in root pointer block and write page 1 310 */ 311 if ((hp = ml_new_ptr(mfp)) == NULL) 312 goto error; 313 if (hp->bh_bnum != 1) 314 { 315 EMSG(_("E298: Didn't get block nr 1?")); 316 goto error; 317 } 318 pp = (PTR_BL *)(hp->bh_data); 319 pp->pb_count = 1; 320 pp->pb_pointer[0].pe_bnum = 2; 321 pp->pb_pointer[0].pe_page_count = 1; 322 pp->pb_pointer[0].pe_old_lnum = 1; 323 pp->pb_pointer[0].pe_line_count = 1; /* line count after insertion */ 324 mf_put(mfp, hp, TRUE, FALSE); 325 326 /* 327 * allocate first data block and create an empty line 1. 328 */ 329 if ((hp = ml_new_data(mfp, FALSE, 1)) == NULL) 330 goto error; 331 if (hp->bh_bnum != 2) 332 { 333 EMSG(_("E298: Didn't get block nr 2?")); 334 goto error; 335 } 336 337 dp = (DATA_BL *)(hp->bh_data); 338 dp->db_index[0] = --dp->db_txt_start; /* at end of block */ 339 dp->db_free -= 1 + INDEX_SIZE; 340 dp->db_line_count = 1; 341 *((char_u *)dp + dp->db_txt_start) = NUL; /* emtpy line */ 342 343 return OK; 344 345 error: 346 if (mfp != NULL) 347 { 348 if (hp) 349 mf_put(mfp, hp, FALSE, FALSE); 350 mf_close(mfp, TRUE); /* will also free(mfp->mf_fname) */ 351 } 352 curbuf->b_ml.ml_mfp = NULL; 353 return FAIL; 354 } 355 356 /* 357 * ml_setname() is called when the file name of "buf" has been changed. 358 * It may rename the swap file. 359 */ 360 void 361 ml_setname(buf) 362 buf_T *buf; 363 { 364 int success = FALSE; 365 memfile_T *mfp; 366 char_u *fname; 367 char_u *dirp; 368 #if defined(MSDOS) || defined(MSWIN) 369 char_u *p; 370 #endif 371 372 mfp = buf->b_ml.ml_mfp; 373 if (mfp->mf_fd < 0) /* there is no swap file yet */ 374 { 375 /* 376 * When 'updatecount' is 0 and 'noswapfile' there is no swap file. 377 * For help files we will make a swap file now. 378 */ 379 if (p_uc != 0) 380 ml_open_file(buf); /* create a swap file */ 381 return; 382 } 383 384 /* 385 * Try all directories in the 'directory' option. 386 */ 387 dirp = p_dir; 388 for (;;) 389 { 390 if (*dirp == NUL) /* tried all directories, fail */ 391 break; 392 fname = findswapname(buf, &dirp, mfp->mf_fname); /* alloc's fname */ 393 if (fname == NULL) /* no file name found for this dir */ 394 continue; 395 396 #if defined(MSDOS) || defined(MSWIN) 397 /* 398 * Set full pathname for swap file now, because a ":!cd dir" may 399 * change directory without us knowing it. 400 */ 401 p = FullName_save(fname, FALSE); 402 vim_free(fname); 403 fname = p; 404 if (fname == NULL) 405 continue; 406 #endif 407 /* if the file name is the same we don't have to do anything */ 408 if (fnamecmp(fname, mfp->mf_fname) == 0) 409 { 410 vim_free(fname); 411 success = TRUE; 412 break; 413 } 414 /* need to close the swap file before renaming */ 415 if (mfp->mf_fd >= 0) 416 { 417 close(mfp->mf_fd); 418 mfp->mf_fd = -1; 419 } 420 421 /* try to rename the swap file */ 422 if (vim_rename(mfp->mf_fname, fname) == 0) 423 { 424 success = TRUE; 425 vim_free(mfp->mf_fname); 426 mfp->mf_fname = fname; 427 vim_free(mfp->mf_ffname); 428 #if defined(MSDOS) || defined(MSWIN) 429 mfp->mf_ffname = NULL; /* mf_fname is full pathname already */ 430 #else 431 mf_set_ffname(mfp); 432 #endif 433 break; 434 } 435 vim_free(fname); /* this fname didn't work, try another */ 436 } 437 438 if (mfp->mf_fd == -1) /* need to (re)open the swap file */ 439 { 440 mfp->mf_fd = mch_open((char *)mfp->mf_fname, O_RDWR | O_EXTRA, 0); 441 if (mfp->mf_fd < 0) 442 { 443 /* could not (re)open the swap file, what can we do???? */ 444 EMSG(_("E301: Oops, lost the swap file!!!")); 445 return; 446 } 447 } 448 if (!success) 449 EMSG(_("E302: Could not rename swap file")); 450 } 451 452 /* 453 * Open a file for the memfile for all buffers that are not readonly or have 454 * been modified. 455 * Used when 'updatecount' changes from zero to non-zero. 456 */ 457 void 458 ml_open_files() 459 { 460 buf_T *buf; 461 462 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 463 if (!buf->b_p_ro || buf->b_changed) 464 ml_open_file(buf); 465 } 466 467 /* 468 * Open a swap file for an existing memfile, if there is no swap file yet. 469 * If we are unable to find a file name, mf_fname will be NULL 470 * and the memfile will be in memory only (no recovery possible). 471 */ 472 void 473 ml_open_file(buf) 474 buf_T *buf; 475 { 476 memfile_T *mfp; 477 char_u *fname; 478 char_u *dirp; 479 480 mfp = buf->b_ml.ml_mfp; 481 if (mfp == NULL || mfp->mf_fd >= 0 || !buf->b_p_swf) 482 return; /* nothing to do */ 483 484 /* 485 * Try all directories in 'directory' option. 486 */ 487 dirp = p_dir; 488 for (;;) 489 { 490 if (*dirp == NUL) 491 break; 492 /* There is a small chance that between chosing the swap file name and 493 * creating it, another Vim creates the file. In that case the 494 * creation will fail and we will use another directory. */ 495 fname = findswapname(buf, &dirp, NULL); /* allocates fname */ 496 if (fname == NULL) 497 continue; 498 if (mf_open_file(mfp, fname) == OK) /* consumes fname! */ 499 { 500 #if defined(MSDOS) || defined(MSWIN) || defined(RISCOS) 501 /* 502 * set full pathname for swap file now, because a ":!cd dir" may 503 * change directory without us knowing it. 504 */ 505 mf_fullname(mfp); 506 #endif 507 /* Flush block zero, so others can read it */ 508 if (mf_sync(mfp, MFS_ZERO) == OK) 509 break; 510 /* Writing block 0 failed: close the file and try another dir */ 511 mf_close_file(buf, FALSE); 512 } 513 } 514 515 if (mfp->mf_fname == NULL) /* Failed! */ 516 { 517 need_wait_return = TRUE; /* call wait_return later */ 518 ++no_wait_return; 519 (void)EMSG2(_("E303: Unable to open swap file for \"%s\", recovery impossible"), 520 buf_spname(buf) != NULL 521 ? (char_u *)buf_spname(buf) 522 : buf->b_fname); 523 --no_wait_return; 524 } 525 526 /* don't try to open a swap file again */ 527 buf->b_may_swap = FALSE; 528 } 529 530 /* 531 * If still need to create a swap file, and starting to edit a not-readonly 532 * file, or reading into an existing buffer, create a swap file now. 533 */ 534 void 535 check_need_swap(newfile) 536 int newfile; /* reading file into new buffer */ 537 { 538 if (curbuf->b_may_swap && (!curbuf->b_p_ro || !newfile)) 539 ml_open_file(curbuf); 540 } 541 542 /* 543 * Close memline for buffer 'buf'. 544 * If 'del_file' is TRUE, delete the swap file 545 */ 546 void 547 ml_close(buf, del_file) 548 buf_T *buf; 549 int del_file; 550 { 551 if (buf->b_ml.ml_mfp == NULL) /* not open */ 552 return; 553 mf_close(buf->b_ml.ml_mfp, del_file); /* close the .swp file */ 554 if (buf->b_ml.ml_line_lnum != 0 && (buf->b_ml.ml_flags & ML_LINE_DIRTY)) 555 vim_free(buf->b_ml.ml_line_ptr); 556 vim_free(buf->b_ml.ml_stack); 557 #ifdef FEAT_BYTEOFF 558 vim_free(buf->b_ml.ml_chunksize); 559 buf->b_ml.ml_chunksize = NULL; 560 #endif 561 buf->b_ml.ml_mfp = NULL; 562 563 /* Reset the "recovered" flag, give the ATTENTION prompt the next time 564 * this buffer is loaded. */ 565 buf->b_flags &= ~BF_RECOVERED; 566 } 567 568 /* 569 * Close all existing memlines and memfiles. 570 * Only used when exiting. 571 * When 'del_file' is TRUE, delete the memfiles. 572 */ 573 void 574 ml_close_all(del_file) 575 int del_file; 576 { 577 buf_T *buf; 578 579 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 580 ml_close(buf, del_file); 581 #ifdef TEMPDIRNAMES 582 vim_deltempdir(); /* delete created temp directory */ 583 #endif 584 } 585 586 /* 587 * Close all memfiles for not modified buffers. 588 * Only use just before exiting! 589 */ 590 void 591 ml_close_notmod() 592 { 593 buf_T *buf; 594 595 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 596 if (!bufIsChanged(buf)) 597 ml_close(buf, TRUE); /* close all not-modified buffers */ 598 } 599 600 /* 601 * Update the timestamp in the .swp file. 602 * Used when the file has been written. 603 */ 604 void 605 ml_timestamp(buf) 606 buf_T *buf; 607 { 608 memfile_T *mfp; 609 bhdr_T *hp; 610 ZERO_BL *b0p; 611 612 mfp = buf->b_ml.ml_mfp; 613 614 if (mfp == NULL || (hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL) 615 return; 616 b0p = (ZERO_BL *)(hp->bh_data); 617 if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1) 618 EMSG(_("E304: ml_timestamp: Didn't get block 0??")); 619 else 620 set_b0_fname(b0p, buf); 621 mf_put(mfp, hp, TRUE, FALSE); 622 } 623 624 /* 625 * Write file name and timestamp into block 0 of a swap file. 626 * Also set buf->b_mtime. 627 * Don't use NameBuff[]!!! 628 */ 629 static void 630 set_b0_fname(b0p, buf) 631 ZERO_BL *b0p; 632 buf_T *buf; 633 { 634 struct stat st; 635 636 if (buf->b_ffname == NULL) 637 b0p->b0_fname[0] = NUL; 638 else 639 { 640 #if defined(MSDOS) || defined(MSWIN) || defined(AMIGA) || defined(RISCOS) 641 /* systems that cannot translate "~user" back into a path: copy the 642 * file name unmodified */ 643 STRNCPY(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE); 644 #else 645 size_t flen, ulen; 646 char_u uname[B0_UNAME_SIZE]; 647 648 /* 649 * For a file under the home directory of the current user, we try to 650 * replace the home directory path with "~user". This helps when 651 * editing the same file on different machines over a network. 652 * First replace home dir path with "~/" with home_replace(). 653 * Then insert the user name to get "~user/". 654 */ 655 home_replace(NULL, buf->b_ffname, b0p->b0_fname, B0_FNAME_SIZE, TRUE); 656 if (b0p->b0_fname[0] == '~') 657 { 658 flen = STRLEN(b0p->b0_fname); 659 /* If there is no user name or it is too long, don't use "~/" */ 660 if (get_user_name(uname, B0_UNAME_SIZE) == FAIL 661 || (ulen = STRLEN(uname)) + flen > B0_FNAME_SIZE - 1) 662 STRNCPY(b0p->b0_fname, buf->b_ffname, B0_FNAME_SIZE); 663 else 664 { 665 mch_memmove(b0p->b0_fname + ulen + 1, b0p->b0_fname + 1, flen); 666 mch_memmove(b0p->b0_fname + 1, uname, ulen); 667 } 668 } 669 #endif 670 if (mch_stat((char *)buf->b_ffname, &st) >= 0) 671 { 672 long_to_char((long)st.st_mtime, b0p->b0_mtime); 673 #ifdef CHECK_INODE 674 long_to_char((long)st.st_ino, b0p->b0_ino); 675 #endif 676 buf_store_time(buf, &st, buf->b_ffname); 677 buf->b_mtime_read = buf->b_mtime; 678 } 679 else 680 { 681 long_to_char(0L, b0p->b0_mtime); 682 #ifdef CHECK_INODE 683 long_to_char(0L, b0p->b0_ino); 684 #endif 685 buf->b_mtime = 0; 686 buf->b_mtime_read = 0; 687 buf->b_orig_size = 0; 688 buf->b_orig_mode = 0; 689 } 690 } 691 } 692 693 /* 694 * try to recover curbuf from the .swp file 695 */ 696 void 697 ml_recover() 698 { 699 buf_T *buf = NULL; 700 memfile_T *mfp = NULL; 701 char_u *fname; 702 bhdr_T *hp = NULL; 703 ZERO_BL *b0p; 704 PTR_BL *pp; 705 DATA_BL *dp; 706 infoptr_T *ip; 707 blocknr_T bnum; 708 int page_count; 709 struct stat org_stat, swp_stat; 710 int len; 711 int directly; 712 linenr_T lnum; 713 char_u *p; 714 int i; 715 long error; 716 int cannot_open; 717 linenr_T line_count; 718 int has_error; 719 int idx; 720 int top; 721 int txt_start; 722 off_t size; 723 int called_from_main; 724 int serious_error = TRUE; 725 long mtime; 726 int attr; 727 728 recoverymode = TRUE; 729 called_from_main = (curbuf->b_ml.ml_mfp == NULL); 730 attr = hl_attr(HLF_E); 731 /* 732 * If the file name ends in ".sw?" we use it directly. 733 * Otherwise a search is done to find the swap file(s). 734 */ 735 fname = curbuf->b_fname; 736 if (fname == NULL) /* When there is no file name */ 737 fname = (char_u *)""; 738 len = (int)STRLEN(fname); 739 if (len >= 4 && 740 #if defined(VMS) || defined(RISCOS) 741 STRNICMP(fname + len - 4, "_sw" , 3) 742 #else 743 STRNICMP(fname + len - 4, ".sw" , 3) 744 #endif 745 == 0) 746 { 747 directly = TRUE; 748 fname = vim_strsave(fname); /* make a copy for mf_open() */ 749 } 750 else 751 { 752 directly = FALSE; 753 754 /* count the number of matching swap files */ 755 len = recover_names(&fname, FALSE, 0); 756 if (len == 0) /* no swap files found */ 757 { 758 EMSG2(_("E305: No swap file found for %s"), fname); 759 goto theend; 760 } 761 if (len == 1) /* one swap file found, use it */ 762 i = 1; 763 else /* several swap files found, choose */ 764 { 765 /* list the names of the swap files */ 766 (void)recover_names(&fname, TRUE, 0); 767 msg_putchar('\n'); 768 MSG_PUTS(_("Enter number of swap file to use (0 to quit): ")); 769 i = get_number(FALSE); 770 if (i < 1 || i > len) 771 goto theend; 772 } 773 /* get the swap file name that will be used */ 774 (void)recover_names(&fname, FALSE, i); 775 } 776 if (fname == NULL) 777 goto theend; /* out of memory */ 778 779 /* When called from main() still need to initialize storage structure */ 780 if (called_from_main && ml_open() == FAIL) 781 getout(1); 782 783 /* 784 * allocate a buffer structure (only the memline in it is really used) 785 */ 786 buf = (buf_T *)alloc((unsigned)sizeof(buf_T)); 787 if (buf == NULL) 788 { 789 vim_free(fname); 790 goto theend; 791 } 792 793 /* 794 * init fields in memline struct 795 */ 796 buf->b_ml.ml_stack_size = 0; /* no stack yet */ 797 buf->b_ml.ml_stack = NULL; /* no stack yet */ 798 buf->b_ml.ml_stack_top = 0; /* nothing in the stack */ 799 buf->b_ml.ml_line_lnum = 0; /* no cached line */ 800 buf->b_ml.ml_locked = NULL; /* no locked block */ 801 buf->b_ml.ml_flags = 0; 802 803 /* 804 * open the memfile from the old swap file 805 */ 806 p = vim_strsave(fname); /* save fname for the message 807 (mf_open() may free fname) */ 808 mfp = mf_open(fname, O_RDONLY); /* consumes fname! */ 809 if (mfp == NULL || mfp->mf_fd < 0) 810 { 811 if (p != NULL) 812 { 813 EMSG2(_("E306: Cannot open %s"), p); 814 vim_free(p); 815 } 816 goto theend; 817 } 818 vim_free(p); 819 buf->b_ml.ml_mfp = mfp; 820 821 /* 822 * The page size set in mf_open() might be different from the page size 823 * used in the swap file, we must get it from block 0. But to read block 824 * 0 we need a page size. Use the minimal size for block 0 here, it will 825 * be set to the real value below. 826 */ 827 mfp->mf_page_size = MIN_SWAP_PAGE_SIZE; 828 829 /* 830 * try to read block 0 831 */ 832 if ((hp = mf_get(mfp, (blocknr_T)0, 1)) == NULL) 833 { 834 msg_start(); 835 MSG_PUTS_ATTR(_("Unable to read block 0 from "), attr | MSG_HIST); 836 msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST); 837 MSG_PUTS_ATTR( 838 _("\nMaybe no changes were made or Vim did not update the swap file."), 839 attr | MSG_HIST); 840 msg_end(); 841 goto theend; 842 } 843 b0p = (ZERO_BL *)(hp->bh_data); 844 if (STRNCMP(b0p->b0_version, "VIM 3.0", 7) == 0) 845 { 846 msg_start(); 847 msg_outtrans_attr(mfp->mf_fname, MSG_HIST); 848 MSG_PUTS_ATTR(_(" cannot be used with this version of Vim.\n"), 849 MSG_HIST); 850 MSG_PUTS_ATTR(_("Use Vim version 3.0.\n"), MSG_HIST); 851 msg_end(); 852 goto theend; 853 } 854 if (b0p->b0_id[0] != BLOCK0_ID0 || b0p->b0_id[1] != BLOCK0_ID1) 855 { 856 EMSG2(_("E307: %s does not look like a Vim swap file"), mfp->mf_fname); 857 goto theend; 858 } 859 if (b0_magic_wrong(b0p)) 860 { 861 msg_start(); 862 msg_outtrans_attr(mfp->mf_fname, attr | MSG_HIST); 863 #if defined(MSDOS) || defined(MSWIN) 864 if (STRNCMP(b0p->b0_hname, "PC ", 3) == 0) 865 MSG_PUTS_ATTR(_(" cannot be used with this version of Vim.\n"), 866 attr | MSG_HIST); 867 else 868 #endif 869 MSG_PUTS_ATTR(_(" cannot be used on this computer.\n"), 870 attr | MSG_HIST); 871 MSG_PUTS_ATTR(_("The file was created on "), attr | MSG_HIST); 872 /* avoid going past the end of a currupted hostname */ 873 b0p->b0_fname[0] = NUL; 874 MSG_PUTS_ATTR(b0p->b0_hname, attr | MSG_HIST); 875 MSG_PUTS_ATTR(_(",\nor the file has been damaged."), attr | MSG_HIST); 876 msg_end(); 877 goto theend; 878 } 879 /* 880 * If we guessed the wrong page size, we have to recalculate the 881 * highest block number in the file. 882 */ 883 if (mfp->mf_page_size != (unsigned)char_to_long(b0p->b0_page_size)) 884 { 885 mf_new_page_size(mfp, (unsigned)char_to_long(b0p->b0_page_size)); 886 if ((size = lseek(mfp->mf_fd, (off_t)0L, SEEK_END)) <= 0) 887 mfp->mf_blocknr_max = 0; /* no file or empty file */ 888 else 889 mfp->mf_blocknr_max = (blocknr_T)(size / mfp->mf_page_size); 890 mfp->mf_infile_count = mfp->mf_blocknr_max; 891 } 892 893 /* 894 * If .swp file name given directly, use name from swap file for buffer. 895 */ 896 if (directly) 897 { 898 expand_env(b0p->b0_fname, NameBuff, MAXPATHL); 899 if (setfname(curbuf, NameBuff, NULL, TRUE) == FAIL) 900 goto theend; 901 } 902 903 home_replace(NULL, mfp->mf_fname, NameBuff, MAXPATHL, TRUE); 904 msg_str((char_u *)_("Using swap file \"%s\""), NameBuff); 905 906 if (buf_spname(curbuf) != NULL) 907 STRCPY(NameBuff, buf_spname(curbuf)); 908 else 909 home_replace(NULL, curbuf->b_ffname, NameBuff, MAXPATHL, TRUE); 910 msg_str((char_u *)_("Original file \"%s\""), NameBuff); 911 msg_putchar('\n'); 912 913 /* 914 * check date of swap file and original file 915 */ 916 mtime = char_to_long(b0p->b0_mtime); 917 if (curbuf->b_ffname != NULL 918 && mch_stat((char *)curbuf->b_ffname, &org_stat) != -1 919 && ((mch_stat((char *)mfp->mf_fname, &swp_stat) != -1 920 && org_stat.st_mtime > swp_stat.st_mtime) 921 || org_stat.st_mtime != mtime)) 922 { 923 EMSG(_("E308: Warning: Original file may have been changed")); 924 } 925 out_flush(); 926 mf_put(mfp, hp, FALSE, FALSE); /* release block 0 */ 927 hp = NULL; 928 929 /* 930 * Now that we are sure that the file is going to be recovered, clear the 931 * contents of the current buffer. 932 */ 933 while (!(curbuf->b_ml.ml_flags & ML_EMPTY)) 934 ml_delete((linenr_T)1, FALSE); 935 936 /* 937 * Try reading the original file to obtain the values of 'fileformat', 938 * 'fileencoding', etc. Ignore errors. The text itself is not used. 939 */ 940 if (curbuf->b_ffname != NULL) 941 { 942 (void)readfile(curbuf->b_ffname, NULL, (linenr_T)0, 943 (linenr_T)0, (linenr_T)MAXLNUM, NULL, READ_NEW); 944 while (!(curbuf->b_ml.ml_flags & ML_EMPTY)) 945 ml_delete((linenr_T)1, FALSE); 946 } 947 948 bnum = 1; /* start with block 1 */ 949 page_count = 1; /* which is 1 page */ 950 lnum = 0; /* append after line 0 in curbuf */ 951 line_count = 0; 952 idx = 0; /* start with first index in block 1 */ 953 error = 0; 954 buf->b_ml.ml_stack_top = 0; 955 buf->b_ml.ml_stack = NULL; 956 buf->b_ml.ml_stack_size = 0; /* no stack yet */ 957 958 if (curbuf->b_ffname == NULL) 959 cannot_open = TRUE; 960 else 961 cannot_open = FALSE; 962 963 serious_error = FALSE; 964 for ( ; !got_int; line_breakcheck()) 965 { 966 if (hp != NULL) 967 mf_put(mfp, hp, FALSE, FALSE); /* release previous block */ 968 969 /* 970 * get block 971 */ 972 if ((hp = mf_get(mfp, (blocknr_T)bnum, page_count)) == NULL) 973 { 974 if (bnum == 1) 975 { 976 EMSG2(_("E309: Unable to read block 1 from %s"), mfp->mf_fname); 977 goto theend; 978 } 979 ++error; 980 ml_append(lnum++, (char_u *)_("???MANY LINES MISSING"), 981 (colnr_T)0, TRUE); 982 } 983 else /* there is a block */ 984 { 985 pp = (PTR_BL *)(hp->bh_data); 986 if (pp->pb_id == PTR_ID) /* it is a pointer block */ 987 { 988 /* check line count when using pointer block first time */ 989 if (idx == 0 && line_count != 0) 990 { 991 for (i = 0; i < (int)pp->pb_count; ++i) 992 line_count -= pp->pb_pointer[i].pe_line_count; 993 if (line_count != 0) 994 { 995 ++error; 996 ml_append(lnum++, (char_u *)_("???LINE COUNT WRONG"), 997 (colnr_T)0, TRUE); 998 } 999 } 1000 1001 if (pp->pb_count == 0) 1002 { 1003 ml_append(lnum++, (char_u *)_("???EMPTY BLOCK"), 1004 (colnr_T)0, TRUE); 1005 ++error; 1006 } 1007 else if (idx < (int)pp->pb_count) /* go a block deeper */ 1008 { 1009 if (pp->pb_pointer[idx].pe_bnum < 0) 1010 { 1011 /* 1012 * Data block with negative block number. 1013 * Try to read lines from the original file. 1014 * This is slow, but it works. 1015 */ 1016 if (!cannot_open) 1017 { 1018 line_count = pp->pb_pointer[idx].pe_line_count; 1019 if (readfile(curbuf->b_ffname, NULL, lnum, 1020 pp->pb_pointer[idx].pe_old_lnum - 1, 1021 line_count, NULL, 0) == FAIL) 1022 cannot_open = TRUE; 1023 else 1024 lnum += line_count; 1025 } 1026 if (cannot_open) 1027 { 1028 ++error; 1029 ml_append(lnum++, (char_u *)_("???LINES MISSING"), 1030 (colnr_T)0, TRUE); 1031 } 1032 ++idx; /* get same block again for next index */ 1033 continue; 1034 } 1035 1036 /* 1037 * going one block deeper in the tree 1038 */ 1039 if ((top = ml_add_stack(buf)) < 0) /* new entry in stack */ 1040 { 1041 ++error; 1042 break; /* out of memory */ 1043 } 1044 ip = &(buf->b_ml.ml_stack[top]); 1045 ip->ip_bnum = bnum; 1046 ip->ip_index = idx; 1047 1048 bnum = pp->pb_pointer[idx].pe_bnum; 1049 line_count = pp->pb_pointer[idx].pe_line_count; 1050 page_count = pp->pb_pointer[idx].pe_page_count; 1051 continue; 1052 } 1053 } 1054 else /* not a pointer block */ 1055 { 1056 dp = (DATA_BL *)(hp->bh_data); 1057 if (dp->db_id != DATA_ID) /* block id wrong */ 1058 { 1059 if (bnum == 1) 1060 { 1061 EMSG2(_("E310: Block 1 ID wrong (%s not a .swp file?)"), 1062 mfp->mf_fname); 1063 goto theend; 1064 } 1065 ++error; 1066 ml_append(lnum++, (char_u *)_("???BLOCK MISSING"), 1067 (colnr_T)0, TRUE); 1068 } 1069 else 1070 { 1071 /* 1072 * it is a data block 1073 * Append all the lines in this block 1074 */ 1075 has_error = FALSE; 1076 /* 1077 * check length of block 1078 * if wrong, use length in pointer block 1079 */ 1080 if (page_count * mfp->mf_page_size != dp->db_txt_end) 1081 { 1082 ml_append(lnum++, (char_u *)_("??? from here until ???END lines may be messed up"), 1083 (colnr_T)0, TRUE); 1084 ++error; 1085 has_error = TRUE; 1086 dp->db_txt_end = page_count * mfp->mf_page_size; 1087 } 1088 1089 /* make sure there is a NUL at the end of the block */ 1090 *((char_u *)dp + dp->db_txt_end - 1) = NUL; 1091 1092 /* 1093 * check number of lines in block 1094 * if wrong, use count in data block 1095 */ 1096 if (line_count != dp->db_line_count) 1097 { 1098 ml_append(lnum++, (char_u *)_("??? from here until ???END lines may have been inserted/deleted"), 1099 (colnr_T)0, TRUE); 1100 ++error; 1101 has_error = TRUE; 1102 } 1103 1104 for (i = 0; i < dp->db_line_count; ++i) 1105 { 1106 txt_start = (dp->db_index[i] & DB_INDEX_MASK); 1107 if (txt_start <= HEADER_SIZE 1108 || txt_start >= (int)dp->db_txt_end) 1109 { 1110 p = (char_u *)"???"; 1111 ++error; 1112 } 1113 else 1114 p = (char_u *)dp + txt_start; 1115 ml_append(lnum++, p, (colnr_T)0, TRUE); 1116 } 1117 if (has_error) 1118 ml_append(lnum++, (char_u *)_("???END"), (colnr_T)0, TRUE); 1119 } 1120 } 1121 } 1122 1123 if (buf->b_ml.ml_stack_top == 0) /* finished */ 1124 break; 1125 1126 /* 1127 * go one block up in the tree 1128 */ 1129 ip = &(buf->b_ml.ml_stack[--(buf->b_ml.ml_stack_top)]); 1130 bnum = ip->ip_bnum; 1131 idx = ip->ip_index + 1; /* go to next index */ 1132 page_count = 1; 1133 } 1134 1135 /* 1136 * The dummy line from the empty buffer will now be after the last line in 1137 * the buffer. Delete it. 1138 */ 1139 ml_delete(curbuf->b_ml.ml_line_count, FALSE); 1140 curbuf->b_flags |= BF_RECOVERED; 1141 1142 recoverymode = FALSE; 1143 if (got_int) 1144 EMSG(_("E311: Recovery Interrupted")); 1145 else if (error) 1146 { 1147 ++no_wait_return; 1148 MSG(">>>>>>>>>>>>>"); 1149 EMSG(_("E312: Errors detected while recovering; look for lines starting with ???")); 1150 --no_wait_return; 1151 MSG(_("See \":help E312\" for more information.")); 1152 MSG(">>>>>>>>>>>>>"); 1153 } 1154 else 1155 { 1156 MSG(_("Recovery completed. You should check if everything is OK.")); 1157 MSG_PUTS(_("\n(You might want to write out this file under another name\n")); 1158 MSG_PUTS(_("and run diff with the original file to check for changes)\n")); 1159 MSG_PUTS(_("Delete the .swp file afterwards.\n\n")); 1160 cmdline_row = msg_row; 1161 } 1162 redraw_curbuf_later(NOT_VALID); 1163 1164 theend: 1165 recoverymode = FALSE; 1166 if (mfp != NULL) 1167 { 1168 if (hp != NULL) 1169 mf_put(mfp, hp, FALSE, FALSE); 1170 mf_close(mfp, FALSE); /* will also vim_free(mfp->mf_fname) */ 1171 } 1172 vim_free(buf); 1173 if (serious_error && called_from_main) 1174 ml_close(curbuf, TRUE); 1175 #ifdef FEAT_AUTOCMD 1176 else 1177 { 1178 apply_autocmds(EVENT_BUFREADPOST, NULL, curbuf->b_fname, FALSE, curbuf); 1179 apply_autocmds(EVENT_BUFWINENTER, NULL, curbuf->b_fname, FALSE, curbuf); 1180 } 1181 #endif 1182 return; 1183 } 1184 1185 /* 1186 * Find the names of swap files in current directory and the directory given 1187 * with the 'directory' option. 1188 * 1189 * Used to: 1190 * - list the swap files for "vim -r" 1191 * - count the number of swap files when recovering 1192 * - list the swap files when recovering 1193 * - find the name of the n'th swap file when recovering 1194 */ 1195 int 1196 recover_names(fname, list, nr) 1197 char_u **fname; /* base for swap file name */ 1198 int list; /* when TRUE, list the swap file names */ 1199 int nr; /* when non-zero, return nr'th swap file name */ 1200 { 1201 int num_names; 1202 char_u *(names[6]); 1203 char_u *tail; 1204 char_u *p; 1205 int num_files; 1206 int file_count = 0; 1207 char_u **files; 1208 int i; 1209 char_u *dirp; 1210 char_u *dir_name; 1211 1212 if (list) 1213 { 1214 /* use msg() to start the scrolling properly */ 1215 msg((char_u *)_("Swap files found:")); 1216 msg_putchar('\n'); 1217 } 1218 1219 /* 1220 * Do the loop for every directory in 'directory'. 1221 * First allocate some memory to put the directory name in. 1222 */ 1223 dir_name = alloc((unsigned)STRLEN(p_dir) + 1); 1224 dirp = p_dir; 1225 while (dir_name != NULL && *dirp) 1226 { 1227 /* 1228 * Isolate a directory name from *dirp and put it in dir_name (we know 1229 * it is large enough, so use 31000 for length). 1230 * Advance dirp to next directory name. 1231 */ 1232 (void)copy_option_part(&dirp, dir_name, 31000, ","); 1233 1234 if (dir_name[0] == '.' && dir_name[1] == NUL) /* check current dir */ 1235 { 1236 if (fname == NULL || *fname == NULL) 1237 { 1238 #ifdef VMS 1239 names[0] = vim_strsave((char_u *)"*_sw%"); 1240 #else 1241 # ifdef RISCOS 1242 names[0] = vim_strsave((char_u *)"*_sw#"); 1243 # else 1244 names[0] = vim_strsave((char_u *)"*.sw?"); 1245 # endif 1246 #endif 1247 #ifdef UNIX 1248 /* for Unix names starting with a dot are special */ 1249 names[1] = vim_strsave((char_u *)".*.sw?"); 1250 names[2] = vim_strsave((char_u *)".sw?"); 1251 num_names = 3; 1252 #else 1253 # ifdef VMS 1254 names[1] = vim_strsave((char_u *)".*_sw%"); 1255 num_names = 2; 1256 # else 1257 num_names = 1; 1258 # endif 1259 #endif 1260 } 1261 else 1262 num_names = recov_file_names(names, *fname, TRUE); 1263 } 1264 else /* check directory dir_name */ 1265 { 1266 if (fname == NULL || *fname == NULL) 1267 { 1268 #ifdef VMS 1269 names[0] = concat_fnames(dir_name, (char_u *)"*_sw%", TRUE); 1270 #else 1271 # ifdef RISCOS 1272 names[0] = concat_fnames(dir_name, (char_u *)"*_sw#", TRUE); 1273 # else 1274 names[0] = concat_fnames(dir_name, (char_u *)"*.sw?", TRUE); 1275 # endif 1276 #endif 1277 #ifdef UNIX 1278 /* for Unix names starting with a dot are special */ 1279 names[1] = concat_fnames(dir_name, (char_u *)".*.sw?", TRUE); 1280 names[2] = concat_fnames(dir_name, (char_u *)".sw?", TRUE); 1281 num_names = 3; 1282 #else 1283 # ifdef VMS 1284 names[1] = concat_fnames(dir_name, (char_u *)".*_sw%", TRUE); 1285 num_names = 2; 1286 # else 1287 num_names = 1; 1288 # endif 1289 #endif 1290 } 1291 else 1292 { 1293 #if defined(UNIX) || defined(WIN3264) 1294 p = dir_name + STRLEN(dir_name); 1295 if (vim_ispathsep(p[-1]) && p[-1] == p[-2]) 1296 { 1297 /* Ends with '//', Use Full path for swap name */ 1298 tail = make_percent_swname(dir_name, *fname); 1299 } 1300 else 1301 #endif 1302 { 1303 tail = gettail(*fname); 1304 tail = concat_fnames(dir_name, tail, TRUE); 1305 } 1306 if (tail == NULL) 1307 num_names = 0; 1308 else 1309 { 1310 num_names = recov_file_names(names, tail, FALSE); 1311 vim_free(tail); 1312 } 1313 } 1314 } 1315 1316 /* check for out-of-memory */ 1317 for (i = 0; i < num_names; ++i) 1318 { 1319 if (names[i] == NULL) 1320 { 1321 for (i = 0; i < num_names; ++i) 1322 vim_free(names[i]); 1323 num_names = 0; 1324 } 1325 } 1326 if (num_names == 0) 1327 num_files = 0; 1328 else if (expand_wildcards(num_names, names, &num_files, &files, 1329 EW_KEEPALL|EW_FILE|EW_SILENT) == FAIL) 1330 num_files = 0; 1331 1332 /* 1333 * When no swap file found, wildcard expansion might have failed (e.g. 1334 * not able to execute the shell). 1335 * Try finding a swap file by simply adding ".swp" to the file name. 1336 */ 1337 if (*dirp == NUL && file_count + num_files == 0 1338 && fname != NULL && *fname != NULL) 1339 { 1340 struct stat st; 1341 char_u *swapname; 1342 1343 #if defined(VMS) || defined(RISCOS) 1344 swapname = modname(*fname, (char_u *)"_swp", FALSE); 1345 #else 1346 swapname = modname(*fname, (char_u *)".swp", TRUE); 1347 #endif 1348 if (swapname != NULL) 1349 { 1350 if (mch_stat((char *)swapname, &st) != -1) /* It exists! */ 1351 { 1352 files = (char_u **)alloc((unsigned)sizeof(char_u *)); 1353 if (files != NULL) 1354 { 1355 files[0] = swapname; 1356 swapname = NULL; 1357 num_files = 1; 1358 } 1359 } 1360 vim_free(swapname); 1361 } 1362 } 1363 1364 /* 1365 * remove swapfile name of the current buffer, it must be ignored 1366 */ 1367 if (curbuf->b_ml.ml_mfp != NULL 1368 && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL) 1369 { 1370 for (i = 0; i < num_files; ++i) 1371 if (fullpathcmp(p, files[i], TRUE) & FPC_SAME) 1372 { 1373 vim_free(files[i]); 1374 --num_files; 1375 for ( ; i < num_files; ++i) 1376 files[i] = files[i + 1]; 1377 } 1378 } 1379 if (nr) 1380 { 1381 file_count += num_files; 1382 if (nr <= file_count) 1383 { 1384 *fname = vim_strsave(files[nr - 1 + num_files - file_count]); 1385 dirp = (char_u *)""; /* stop searching */ 1386 } 1387 } 1388 else if (list) 1389 { 1390 if (dir_name[0] == '.' && dir_name[1] == NUL) 1391 { 1392 if (fname == NULL || *fname == NULL) 1393 MSG_PUTS(_(" In current directory:\n")); 1394 else 1395 MSG_PUTS(_(" Using specified name:\n")); 1396 } 1397 else 1398 { 1399 MSG_PUTS(_(" In directory ")); 1400 msg_home_replace(dir_name); 1401 MSG_PUTS(":\n"); 1402 } 1403 1404 if (num_files) 1405 { 1406 for (i = 0; i < num_files; ++i) 1407 { 1408 /* print the swap file name */ 1409 msg_outnum((long)++file_count); 1410 MSG_PUTS(". "); 1411 msg_puts(gettail(files[i])); 1412 msg_putchar('\n'); 1413 (void)swapfile_info(files[i]); 1414 } 1415 } 1416 else 1417 MSG_PUTS(_(" -- none --\n")); 1418 out_flush(); 1419 } 1420 else 1421 file_count += num_files; 1422 1423 for (i = 0; i < num_names; ++i) 1424 vim_free(names[i]); 1425 FreeWild(num_files, files); 1426 } 1427 vim_free(dir_name); 1428 return file_count; 1429 } 1430 1431 #if defined(UNIX) || defined(WIN3264) /* Need _very_ long file names */ 1432 /* 1433 * Append the full path to name with path separators made into percent 1434 * signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"") 1435 */ 1436 static char_u * 1437 make_percent_swname(dir, name) 1438 char_u *dir; 1439 char_u *name; 1440 { 1441 char_u *d, *s, *f, *p; 1442 1443 f = fix_fname(name != NULL ? name : (char_u *) ""); 1444 d = NULL; 1445 if (f != NULL) 1446 { 1447 s = alloc((unsigned)(STRLEN(f) + 1)); 1448 if (s != NULL) 1449 { 1450 for (d = s, p = f; *p; p++, d++) 1451 *d = vim_ispathsep(*p) ? '%' : *p; 1452 *d = 0; 1453 d = concat_fnames(dir, s, TRUE); 1454 vim_free(s); 1455 } 1456 vim_free(f); 1457 } 1458 return d; 1459 } 1460 #endif 1461 1462 #if (defined(UNIX) || defined(__EMX__) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)) 1463 static int process_still_running; 1464 #endif 1465 1466 /* 1467 * Give information about an existing swap file 1468 * Returns timestamp (0 when unknown). 1469 */ 1470 static time_t 1471 swapfile_info(fname) 1472 char_u *fname; 1473 { 1474 struct stat st; 1475 int fd; 1476 struct block0 b0; 1477 time_t x = (time_t)0; 1478 #ifdef UNIX 1479 char_u uname[B0_UNAME_SIZE]; 1480 #endif 1481 1482 /* print the swap file date */ 1483 if (mch_stat((char *)fname, &st) != -1) 1484 { 1485 #ifdef UNIX 1486 /* print name of owner of the file */ 1487 if (mch_get_uname(st.st_uid, uname, B0_UNAME_SIZE) == OK) 1488 { 1489 MSG_PUTS(_(" owned by: ")); 1490 msg_outtrans(uname); 1491 MSG_PUTS(_(" dated: ")); 1492 } 1493 else 1494 #endif 1495 MSG_PUTS(_(" dated: ")); 1496 x = st.st_mtime; /* Manx C can't do &st.st_mtime */ 1497 MSG_PUTS(ctime(&x)); /* includes '\n' */ 1498 1499 } 1500 1501 /* 1502 * print the original file name 1503 */ 1504 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0); 1505 if (fd >= 0) 1506 { 1507 if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0)) 1508 { 1509 if (STRNCMP(b0.b0_version, "VIM 3.0", 7) == 0) 1510 { 1511 MSG_PUTS(_(" [from Vim version 3.0]")); 1512 } 1513 else if (b0.b0_id[0] != BLOCK0_ID0 || b0.b0_id[1] != BLOCK0_ID1) 1514 { 1515 MSG_PUTS(_(" [does not look like a Vim swap file]")); 1516 } 1517 else 1518 { 1519 MSG_PUTS(_(" file name: ")); 1520 if (b0.b0_fname[0] == NUL) 1521 MSG_PUTS(_("[No Name]")); 1522 else 1523 msg_outtrans(b0.b0_fname); 1524 1525 MSG_PUTS(_("\n modified: ")); 1526 MSG_PUTS(b0.b0_dirty ? _("YES") : _("no")); 1527 1528 if (*(b0.b0_uname) != NUL) 1529 { 1530 MSG_PUTS(_("\n user name: ")); 1531 msg_outtrans(b0.b0_uname); 1532 } 1533 1534 if (*(b0.b0_hname) != NUL) 1535 { 1536 if (*(b0.b0_uname) != NUL) 1537 MSG_PUTS(_(" host name: ")); 1538 else 1539 MSG_PUTS(_("\n host name: ")); 1540 msg_outtrans(b0.b0_hname); 1541 } 1542 1543 if (char_to_long(b0.b0_pid) != 0L) 1544 { 1545 MSG_PUTS(_("\n process ID: ")); 1546 msg_outnum(char_to_long(b0.b0_pid)); 1547 #if defined(UNIX) || defined(__EMX__) 1548 /* EMX kill() not working correctly, it seems */ 1549 if (kill((pid_t)char_to_long(b0.b0_pid), 0) == 0) 1550 { 1551 MSG_PUTS(_(" (still running)")); 1552 # if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 1553 process_still_running = TRUE; 1554 # endif 1555 } 1556 #endif 1557 } 1558 1559 if (b0_magic_wrong(&b0)) 1560 { 1561 #if defined(MSDOS) || defined(MSWIN) 1562 if (STRNCMP(b0.b0_hname, "PC ", 3) == 0) 1563 MSG_PUTS(_("\n [not usable with this version of Vim]")); 1564 else 1565 #endif 1566 MSG_PUTS(_("\n [not usable on this computer]")); 1567 } 1568 } 1569 } 1570 else 1571 MSG_PUTS(_(" [cannot be read]")); 1572 close(fd); 1573 } 1574 else 1575 MSG_PUTS(_(" [cannot be opened]")); 1576 msg_putchar('\n'); 1577 1578 return x; 1579 } 1580 1581 static int 1582 recov_file_names(names, path, prepend_dot) 1583 char_u **names; 1584 char_u *path; 1585 int prepend_dot; 1586 { 1587 int num_names; 1588 1589 #ifdef SHORT_FNAME 1590 /* 1591 * (MS-DOS) always short names 1592 */ 1593 names[0] = modname(path, (char_u *)".sw?", FALSE); 1594 num_names = 1; 1595 #else /* !SHORT_FNAME */ 1596 /* 1597 * (Win32 and Win64) never short names, but do prepend a dot. 1598 * (Not MS-DOS or Win32 or Win64) maybe short name, maybe not: Try both. 1599 * Only use the short name if it is different. 1600 */ 1601 char_u *p; 1602 int i; 1603 # ifndef WIN3264 1604 int shortname = curbuf->b_shortname; 1605 1606 curbuf->b_shortname = FALSE; 1607 # endif 1608 1609 num_names = 0; 1610 1611 /* 1612 * May also add the file name with a dot prepended, for swap file in same 1613 * dir as original file. 1614 */ 1615 if (prepend_dot) 1616 { 1617 names[num_names] = modname(path, (char_u *)".sw?", TRUE); 1618 if (names[num_names] == NULL) 1619 goto end; 1620 ++num_names; 1621 } 1622 1623 /* 1624 * Form the normal swap file name pattern by appending ".sw?". 1625 */ 1626 #ifdef VMS 1627 names[num_names] = concat_fnames(path, (char_u *)"_sw%", FALSE); 1628 #else 1629 # ifdef RISCOS 1630 names[num_names] = concat_fnames(path, (char_u *)"_sw#", FALSE); 1631 # else 1632 names[num_names] = concat_fnames(path, (char_u *)".sw?", FALSE); 1633 # endif 1634 #endif 1635 if (names[num_names] == NULL) 1636 goto end; 1637 if (num_names >= 1) /* check if we have the same name twice */ 1638 { 1639 p = names[num_names - 1]; 1640 i = (int)STRLEN(names[num_names - 1]) - (int)STRLEN(names[num_names]); 1641 if (i > 0) 1642 p += i; /* file name has been expanded to full path */ 1643 1644 if (STRCMP(p, names[num_names]) != 0) 1645 ++num_names; 1646 else 1647 vim_free(names[num_names]); 1648 } 1649 else 1650 ++num_names; 1651 1652 # ifndef WIN3264 1653 /* 1654 * Also try with 'shortname' set, in case the file is on a DOS filesystem. 1655 */ 1656 curbuf->b_shortname = TRUE; 1657 #ifdef VMS 1658 names[num_names] = modname(path, (char_u *)"_sw%", FALSE); 1659 #else 1660 # ifdef RISCOS 1661 names[num_names] = modname(path, (char_u *)"_sw#", FALSE); 1662 # else 1663 names[num_names] = modname(path, (char_u *)".sw?", FALSE); 1664 # endif 1665 #endif 1666 if (names[num_names] == NULL) 1667 goto end; 1668 1669 /* 1670 * Remove the one from 'shortname', if it's the same as with 'noshortname'. 1671 */ 1672 p = names[num_names]; 1673 i = STRLEN(names[num_names]) - STRLEN(names[num_names - 1]); 1674 if (i > 0) 1675 p += i; /* file name has been expanded to full path */ 1676 if (STRCMP(names[num_names - 1], p) == 0) 1677 vim_free(names[num_names]); 1678 else 1679 ++num_names; 1680 # endif 1681 1682 end: 1683 # ifndef WIN3264 1684 curbuf->b_shortname = shortname; 1685 # endif 1686 1687 #endif /* !SHORT_FNAME */ 1688 1689 return num_names; 1690 } 1691 1692 /* 1693 * sync all memlines 1694 * 1695 * If 'check_file' is TRUE, check if original file exists and was not changed. 1696 * If 'check_char' is TRUE, stop syncing when character becomes available, but 1697 * always sync at least one block. 1698 */ 1699 void 1700 ml_sync_all(check_file, check_char) 1701 int check_file; 1702 int check_char; 1703 { 1704 buf_T *buf; 1705 struct stat st; 1706 1707 for (buf = firstbuf; buf != NULL; buf = buf->b_next) 1708 { 1709 if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL) 1710 continue; /* no file */ 1711 1712 ml_flush_line(buf); /* flush buffered line */ 1713 /* flush locked block */ 1714 (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); 1715 if (bufIsChanged(buf) && check_file && mf_need_trans(buf->b_ml.ml_mfp) 1716 && buf->b_ffname != NULL) 1717 { 1718 /* 1719 * If the original file does not exist anymore or has been changed 1720 * call ml_preserve() to get rid of all negative numbered blocks. 1721 */ 1722 if (mch_stat((char *)buf->b_ffname, &st) == -1 1723 || st.st_mtime != buf->b_mtime_read 1724 || (size_t)st.st_size != buf->b_orig_size) 1725 { 1726 ml_preserve(buf, FALSE); 1727 did_check_timestamps = FALSE; 1728 need_check_timestamps = TRUE; /* give message later */ 1729 } 1730 } 1731 if (buf->b_ml.ml_mfp->mf_dirty) 1732 { 1733 (void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0) 1734 | (bufIsChanged(buf) ? MFS_FLUSH : 0)); 1735 if (check_char && ui_char_avail()) /* character available now */ 1736 break; 1737 } 1738 } 1739 } 1740 1741 /* 1742 * sync one buffer, including negative blocks 1743 * 1744 * after this all the blocks are in the swap file 1745 * 1746 * Used for the :preserve command and when the original file has been 1747 * changed or deleted. 1748 * 1749 * when message is TRUE the success of preserving is reported 1750 */ 1751 void 1752 ml_preserve(buf, message) 1753 buf_T *buf; 1754 int message; 1755 { 1756 bhdr_T *hp; 1757 linenr_T lnum; 1758 memfile_T *mfp = buf->b_ml.ml_mfp; 1759 int status; 1760 int got_int_save = got_int; 1761 1762 if (mfp == NULL || mfp->mf_fname == NULL) 1763 { 1764 if (message) 1765 EMSG(_("E313: Cannot preserve, there is no swap file")); 1766 return; 1767 } 1768 1769 /* We only want to stop when interrupted here, not when interrupted 1770 * before. */ 1771 got_int = FALSE; 1772 1773 ml_flush_line(buf); /* flush buffered line */ 1774 (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); /* flush locked block */ 1775 status = mf_sync(mfp, MFS_ALL | MFS_FLUSH); 1776 1777 /* stack is invalid after mf_sync(.., MFS_ALL) */ 1778 buf->b_ml.ml_stack_top = 0; 1779 1780 /* 1781 * Some of the data blocks may have been changed from negative to 1782 * positive block number. In that case the pointer blocks need to be 1783 * updated. 1784 * 1785 * We don't know in which pointer block the references are, so we visit 1786 * all data blocks until there are no more translations to be done (or 1787 * we hit the end of the file, which can only happen in case a write fails, 1788 * e.g. when file system if full). 1789 * ml_find_line() does the work by translating the negative block numbers 1790 * when getting the first line of each data block. 1791 */ 1792 if (mf_need_trans(mfp) && !got_int) 1793 { 1794 lnum = 1; 1795 while (mf_need_trans(mfp) && lnum <= buf->b_ml.ml_line_count) 1796 { 1797 hp = ml_find_line(buf, lnum, ML_FIND); 1798 if (hp == NULL) 1799 { 1800 status = FAIL; 1801 goto theend; 1802 } 1803 CHECK(buf->b_ml.ml_locked_low != lnum, "low != lnum"); 1804 lnum = buf->b_ml.ml_locked_high + 1; 1805 } 1806 (void)ml_find_line(buf, (linenr_T)0, ML_FLUSH); /* flush locked block */ 1807 /* sync the updated pointer blocks */ 1808 if (mf_sync(mfp, MFS_ALL | MFS_FLUSH) == FAIL) 1809 status = FAIL; 1810 buf->b_ml.ml_stack_top = 0; /* stack is invalid now */ 1811 } 1812 theend: 1813 got_int |= got_int_save; 1814 1815 if (message) 1816 { 1817 if (status == OK) 1818 MSG(_("File preserved")); 1819 else 1820 EMSG(_("E314: Preserve failed")); 1821 } 1822 } 1823 1824 /* 1825 * NOTE: The pointer returned by the ml_get_*() functions only remains valid 1826 * until the next call! 1827 * line1 = ml_get(1); 1828 * line2 = ml_get(2); // line1 is now invalid! 1829 * Make a copy of the line if necessary. 1830 */ 1831 /* 1832 * get a pointer to a (read-only copy of a) line 1833 * 1834 * On failure an error message is given and IObuff is returned (to avoid 1835 * having to check for error everywhere). 1836 */ 1837 char_u * 1838 ml_get(lnum) 1839 linenr_T lnum; 1840 { 1841 return ml_get_buf(curbuf, lnum, FALSE); 1842 } 1843 1844 /* 1845 * ml_get_pos: get pointer to position 'pos' 1846 */ 1847 char_u * 1848 ml_get_pos(pos) 1849 pos_T *pos; 1850 { 1851 return (ml_get_buf(curbuf, pos->lnum, FALSE) + pos->col); 1852 } 1853 1854 /* 1855 * ml_get_curline: get pointer to cursor line. 1856 */ 1857 char_u * 1858 ml_get_curline() 1859 { 1860 return ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE); 1861 } 1862 1863 /* 1864 * ml_get_cursor: get pointer to cursor position 1865 */ 1866 char_u * 1867 ml_get_cursor() 1868 { 1869 return (ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE) + 1870 curwin->w_cursor.col); 1871 } 1872 1873 /* 1874 * get a pointer to a line in a specific buffer 1875 * 1876 * "will_change": if TRUE mark the buffer dirty (chars in the line will be 1877 * changed) 1878 */ 1879 char_u * 1880 ml_get_buf(buf, lnum, will_change) 1881 buf_T *buf; 1882 linenr_T lnum; 1883 int will_change; /* line will be changed */ 1884 { 1885 bhdr_T *hp; 1886 DATA_BL *dp; 1887 char_u *ptr; 1888 1889 if (lnum > buf->b_ml.ml_line_count) /* invalid line number */ 1890 { 1891 EMSGN(_("E315: ml_get: invalid lnum: %ld"), lnum); 1892 errorret: 1893 STRCPY(IObuff, "???"); 1894 return IObuff; 1895 } 1896 if (lnum <= 0) /* pretend line 0 is line 1 */ 1897 lnum = 1; 1898 1899 if (buf->b_ml.ml_mfp == NULL) /* there are no lines */ 1900 return (char_u *)""; 1901 1902 /* 1903 * See if it is the same line as requested last time. 1904 * Otherwise may need to flush last used line. 1905 */ 1906 if (buf->b_ml.ml_line_lnum != lnum) 1907 { 1908 ml_flush_line(buf); 1909 1910 /* 1911 * Find the data block containing the line. 1912 * This also fills the stack with the blocks from the root to the data 1913 * block and releases any locked block. 1914 */ 1915 if ((hp = ml_find_line(buf, lnum, ML_FIND)) == NULL) 1916 { 1917 EMSGN(_("E316: ml_get: cannot find line %ld"), lnum); 1918 goto errorret; 1919 } 1920 1921 dp = (DATA_BL *)(hp->bh_data); 1922 1923 ptr = (char_u *)dp + ((dp->db_index[lnum - buf->b_ml.ml_locked_low]) & DB_INDEX_MASK); 1924 buf->b_ml.ml_line_ptr = ptr; 1925 buf->b_ml.ml_line_lnum = lnum; 1926 buf->b_ml.ml_flags &= ~ML_LINE_DIRTY; 1927 } 1928 if (will_change) 1929 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); 1930 1931 return buf->b_ml.ml_line_ptr; 1932 } 1933 1934 /* 1935 * Check if a line that was just obtained by a call to ml_get 1936 * is in allocated memory. 1937 */ 1938 int 1939 ml_line_alloced() 1940 { 1941 return (curbuf->b_ml.ml_flags & ML_LINE_DIRTY); 1942 } 1943 1944 /* 1945 * Append a line after lnum (may be 0 to insert a line in front of the file). 1946 * "line" does not need to be allocated, but can't be another line in a 1947 * buffer, unlocking may make it invalid. 1948 * 1949 * newfile: TRUE when starting to edit a new file, meaning that pe_old_lnum 1950 * will be set for recovery 1951 * Check: The caller of this function should probably also call 1952 * appended_lines(). 1953 * 1954 * return FAIL for failure, OK otherwise 1955 */ 1956 int 1957 ml_append(lnum, line, len, newfile) 1958 linenr_T lnum; /* append after this line (can be 0) */ 1959 char_u *line; /* text of the new line */ 1960 colnr_T len; /* length of new line, including NUL, or 0 */ 1961 int newfile; /* flag, see above */ 1962 { 1963 /* When starting up, we might still need to create the memfile */ 1964 if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL) == FAIL) 1965 return FAIL; 1966 1967 if (curbuf->b_ml.ml_line_lnum != 0) 1968 ml_flush_line(curbuf); 1969 return ml_append_int(curbuf, lnum, line, len, newfile, FALSE); 1970 } 1971 1972 static int 1973 ml_append_int(buf, lnum, line, len, newfile, mark) 1974 buf_T *buf; 1975 linenr_T lnum; /* append after this line (can be 0) */ 1976 char_u *line; /* text of the new line */ 1977 colnr_T len; /* length of line, including NUL, or 0 */ 1978 int newfile; /* flag, see above */ 1979 int mark; /* mark the new line */ 1980 { 1981 int i; 1982 int line_count; /* number of indexes in current block */ 1983 int offset; 1984 int from, to; 1985 int space_needed; /* space needed for new line */ 1986 int page_size; 1987 int page_count; 1988 int db_idx; /* index for lnum in data block */ 1989 bhdr_T *hp; 1990 memfile_T *mfp; 1991 DATA_BL *dp; 1992 PTR_BL *pp; 1993 infoptr_T *ip; 1994 1995 /* lnum out of range */ 1996 if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL) 1997 return FAIL; 1998 1999 if (lowest_marked && lowest_marked > lnum) 2000 lowest_marked = lnum + 1; 2001 2002 if (len == 0) 2003 len = (colnr_T)STRLEN(line) + 1; /* space needed for the text */ 2004 space_needed = len + INDEX_SIZE; /* space needed for text + index */ 2005 2006 mfp = buf->b_ml.ml_mfp; 2007 page_size = mfp->mf_page_size; 2008 2009 /* 2010 * find the data block containing the previous line 2011 * This also fills the stack with the blocks from the root to the data block 2012 * This also releases any locked block. 2013 */ 2014 if ((hp = ml_find_line(buf, lnum == 0 ? (linenr_T)1 : lnum, 2015 ML_INSERT)) == NULL) 2016 return FAIL; 2017 2018 buf->b_ml.ml_flags &= ~ML_EMPTY; 2019 2020 if (lnum == 0) /* got line one instead, correct db_idx */ 2021 db_idx = -1; /* careful, it is negative! */ 2022 else 2023 db_idx = lnum - buf->b_ml.ml_locked_low; 2024 /* get line count before the insertion */ 2025 line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low; 2026 2027 dp = (DATA_BL *)(hp->bh_data); 2028 2029 /* 2030 * If 2031 * - there is not enough room in the current block 2032 * - appending to the last line in the block 2033 * - not appending to the last line in the file 2034 * insert in front of the next block. 2035 */ 2036 if ((int)dp->db_free < space_needed && db_idx == line_count - 1 2037 && lnum < buf->b_ml.ml_line_count) 2038 { 2039 /* 2040 * Now that the line is not going to be inserted in the block that we 2041 * expected, the line count has to be adjusted in the pointer blocks 2042 * by using ml_locked_lineadd. 2043 */ 2044 --(buf->b_ml.ml_locked_lineadd); 2045 --(buf->b_ml.ml_locked_high); 2046 if ((hp = ml_find_line(buf, lnum + 1, ML_INSERT)) == NULL) 2047 return FAIL; 2048 2049 db_idx = -1; /* careful, it is negative! */ 2050 /* get line count before the insertion */ 2051 line_count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low; 2052 CHECK(buf->b_ml.ml_locked_low != lnum + 1, "locked_low != lnum + 1"); 2053 2054 dp = (DATA_BL *)(hp->bh_data); 2055 } 2056 2057 ++buf->b_ml.ml_line_count; 2058 2059 if ((int)dp->db_free >= space_needed) /* enough room in data block */ 2060 { 2061 /* 2062 * Insert new line in existing data block, or in data block allocated above. 2063 */ 2064 dp->db_txt_start -= len; 2065 dp->db_free -= space_needed; 2066 ++(dp->db_line_count); 2067 2068 /* 2069 * move the text of the lines that follow to the front 2070 * adjust the indexes of the lines that follow 2071 */ 2072 if (line_count > db_idx + 1) /* if there are following lines */ 2073 { 2074 /* 2075 * Offset is the start of the previous line. 2076 * This will become the character just after the new line. 2077 */ 2078 if (db_idx < 0) 2079 offset = dp->db_txt_end; 2080 else 2081 offset = ((dp->db_index[db_idx]) & DB_INDEX_MASK); 2082 mch_memmove((char *)dp + dp->db_txt_start, 2083 (char *)dp + dp->db_txt_start + len, 2084 (size_t)(offset - (dp->db_txt_start + len))); 2085 for (i = line_count - 1; i > db_idx; --i) 2086 dp->db_index[i + 1] = dp->db_index[i] - len; 2087 dp->db_index[db_idx + 1] = offset - len; 2088 } 2089 else /* add line at the end */ 2090 dp->db_index[db_idx + 1] = dp->db_txt_start; 2091 2092 /* 2093 * copy the text into the block 2094 */ 2095 mch_memmove((char *)dp + dp->db_index[db_idx + 1], line, (size_t)len); 2096 if (mark) 2097 dp->db_index[db_idx + 1] |= DB_MARKED; 2098 2099 /* 2100 * Mark the block dirty. 2101 */ 2102 buf->b_ml.ml_flags |= ML_LOCKED_DIRTY; 2103 if (!newfile) 2104 buf->b_ml.ml_flags |= ML_LOCKED_POS; 2105 } 2106 else /* not enough space in data block */ 2107 { 2108 /* 2109 * If there is not enough room we have to create a new data block and copy some 2110 * lines into it. 2111 * Then we have to insert an entry in the pointer block. 2112 * If this pointer block also is full, we go up another block, and so on, up 2113 * to the root if necessary. 2114 * The line counts in the pointer blocks have already been adjusted by 2115 * ml_find_line(). 2116 */ 2117 long line_count_left, line_count_right; 2118 int page_count_left, page_count_right; 2119 bhdr_T *hp_left; 2120 bhdr_T *hp_right; 2121 bhdr_T *hp_new; 2122 int lines_moved; 2123 int data_moved = 0; /* init to shut up gcc */ 2124 int total_moved = 0; /* init to shut up gcc */ 2125 DATA_BL *dp_right, *dp_left; 2126 int stack_idx; 2127 int in_left; 2128 int lineadd; 2129 blocknr_T bnum_left, bnum_right; 2130 linenr_T lnum_left, lnum_right; 2131 int pb_idx; 2132 PTR_BL *pp_new; 2133 2134 /* 2135 * We are going to allocate a new data block. Depending on the 2136 * situation it will be put to the left or right of the existing 2137 * block. If possible we put the new line in the left block and move 2138 * the lines after it to the right block. Otherwise the new line is 2139 * also put in the right block. This method is more efficient when 2140 * inserting a lot of lines at one place. 2141 */ 2142 if (db_idx < 0) /* left block is new, right block is existing */ 2143 { 2144 lines_moved = 0; 2145 in_left = TRUE; 2146 /* space_needed does not change */ 2147 } 2148 else /* left block is existing, right block is new */ 2149 { 2150 lines_moved = line_count - db_idx - 1; 2151 if (lines_moved == 0) 2152 in_left = FALSE; /* put new line in right block */ 2153 /* space_needed does not change */ 2154 else 2155 { 2156 data_moved = ((dp->db_index[db_idx]) & DB_INDEX_MASK) - 2157 dp->db_txt_start; 2158 total_moved = data_moved + lines_moved * INDEX_SIZE; 2159 if ((int)dp->db_free + total_moved >= space_needed) 2160 { 2161 in_left = TRUE; /* put new line in left block */ 2162 space_needed = total_moved; 2163 } 2164 else 2165 { 2166 in_left = FALSE; /* put new line in right block */ 2167 space_needed += total_moved; 2168 } 2169 } 2170 } 2171 2172 page_count = ((space_needed + HEADER_SIZE) + page_size - 1) / page_size; 2173 if ((hp_new = ml_new_data(mfp, newfile, page_count)) == NULL) 2174 { 2175 /* correct line counts in pointer blocks */ 2176 --(buf->b_ml.ml_locked_lineadd); 2177 --(buf->b_ml.ml_locked_high); 2178 return FAIL; 2179 } 2180 if (db_idx < 0) /* left block is new */ 2181 { 2182 hp_left = hp_new; 2183 hp_right = hp; 2184 line_count_left = 0; 2185 line_count_right = line_count; 2186 } 2187 else /* right block is new */ 2188 { 2189 hp_left = hp; 2190 hp_right = hp_new; 2191 line_count_left = line_count; 2192 line_count_right = 0; 2193 } 2194 dp_right = (DATA_BL *)(hp_right->bh_data); 2195 dp_left = (DATA_BL *)(hp_left->bh_data); 2196 bnum_left = hp_left->bh_bnum; 2197 bnum_right = hp_right->bh_bnum; 2198 page_count_left = hp_left->bh_page_count; 2199 page_count_right = hp_right->bh_page_count; 2200 2201 /* 2202 * May move the new line into the right/new block. 2203 */ 2204 if (!in_left) 2205 { 2206 dp_right->db_txt_start -= len; 2207 dp_right->db_free -= len + INDEX_SIZE; 2208 dp_right->db_index[0] = dp_right->db_txt_start; 2209 if (mark) 2210 dp_right->db_index[0] |= DB_MARKED; 2211 2212 mch_memmove((char *)dp_right + dp_right->db_txt_start, 2213 line, (size_t)len); 2214 ++line_count_right; 2215 } 2216 /* 2217 * may move lines from the left/old block to the right/new one. 2218 */ 2219 if (lines_moved) 2220 { 2221 /* 2222 */ 2223 dp_right->db_txt_start -= data_moved; 2224 dp_right->db_free -= total_moved; 2225 mch_memmove((char *)dp_right + dp_right->db_txt_start, 2226 (char *)dp_left + dp_left->db_txt_start, 2227 (size_t)data_moved); 2228 offset = dp_right->db_txt_start - dp_left->db_txt_start; 2229 dp_left->db_txt_start += data_moved; 2230 dp_left->db_free += total_moved; 2231 2232 /* 2233 * update indexes in the new block 2234 */ 2235 for (to = line_count_right, from = db_idx + 1; 2236 from < line_count_left; ++from, ++to) 2237 dp_right->db_index[to] = dp->db_index[from] + offset; 2238 line_count_right += lines_moved; 2239 line_count_left -= lines_moved; 2240 } 2241 2242 /* 2243 * May move the new line into the left (old or new) block. 2244 */ 2245 if (in_left) 2246 { 2247 dp_left->db_txt_start -= len; 2248 dp_left->db_free -= len + INDEX_SIZE; 2249 dp_left->db_index[line_count_left] = dp_left->db_txt_start; 2250 if (mark) 2251 dp_left->db_index[line_count_left] |= DB_MARKED; 2252 mch_memmove((char *)dp_left + dp_left->db_txt_start, 2253 line, (size_t)len); 2254 ++line_count_left; 2255 } 2256 2257 if (db_idx < 0) /* left block is new */ 2258 { 2259 lnum_left = lnum + 1; 2260 lnum_right = 0; 2261 } 2262 else /* right block is new */ 2263 { 2264 lnum_left = 0; 2265 if (in_left) 2266 lnum_right = lnum + 2; 2267 else 2268 lnum_right = lnum + 1; 2269 } 2270 dp_left->db_line_count = line_count_left; 2271 dp_right->db_line_count = line_count_right; 2272 2273 /* 2274 * release the two data blocks 2275 * The new one (hp_new) already has a correct blocknumber. 2276 * The old one (hp, in ml_locked) gets a positive blocknumber if 2277 * we changed it and we are not editing a new file. 2278 */ 2279 if (lines_moved || in_left) 2280 buf->b_ml.ml_flags |= ML_LOCKED_DIRTY; 2281 if (!newfile && db_idx >= 0 && in_left) 2282 buf->b_ml.ml_flags |= ML_LOCKED_POS; 2283 mf_put(mfp, hp_new, TRUE, FALSE); 2284 2285 /* 2286 * flush the old data block 2287 * set ml_locked_lineadd to 0, because the updating of the 2288 * pointer blocks is done below 2289 */ 2290 lineadd = buf->b_ml.ml_locked_lineadd; 2291 buf->b_ml.ml_locked_lineadd = 0; 2292 ml_find_line(buf, (linenr_T)0, ML_FLUSH); /* flush data block */ 2293 2294 /* 2295 * update pointer blocks for the new data block 2296 */ 2297 for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; 2298 --stack_idx) 2299 { 2300 ip = &(buf->b_ml.ml_stack[stack_idx]); 2301 pb_idx = ip->ip_index; 2302 if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) 2303 return FAIL; 2304 pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */ 2305 if (pp->pb_id != PTR_ID) 2306 { 2307 EMSG(_("E317: pointer block id wrong 3")); 2308 mf_put(mfp, hp, FALSE, FALSE); 2309 return FAIL; 2310 } 2311 /* 2312 * TODO: If the pointer block is full and we are adding at the end 2313 * try to insert in front of the next block 2314 */ 2315 /* block not full, add one entry */ 2316 if (pp->pb_count < pp->pb_count_max) 2317 { 2318 if (pb_idx + 1 < (int)pp->pb_count) 2319 mch_memmove(&pp->pb_pointer[pb_idx + 2], 2320 &pp->pb_pointer[pb_idx + 1], 2321 (size_t)(pp->pb_count - pb_idx - 1) * sizeof(PTR_EN)); 2322 ++pp->pb_count; 2323 pp->pb_pointer[pb_idx].pe_line_count = line_count_left; 2324 pp->pb_pointer[pb_idx].pe_bnum = bnum_left; 2325 pp->pb_pointer[pb_idx].pe_page_count = page_count_left; 2326 pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right; 2327 pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right; 2328 pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right; 2329 2330 if (lnum_left != 0) 2331 pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left; 2332 if (lnum_right != 0) 2333 pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right; 2334 2335 mf_put(mfp, hp, TRUE, FALSE); 2336 buf->b_ml.ml_stack_top = stack_idx + 1; /* truncate stack */ 2337 2338 if (lineadd) 2339 { 2340 --(buf->b_ml.ml_stack_top); 2341 /* fix line count for rest of blocks in the stack */ 2342 ml_lineadd(buf, lineadd); 2343 /* fix stack itself */ 2344 buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high += 2345 lineadd; 2346 ++(buf->b_ml.ml_stack_top); 2347 } 2348 2349 /* 2350 * We are finished, break the loop here. 2351 */ 2352 break; 2353 } 2354 else /* pointer block full */ 2355 { 2356 /* 2357 * split the pointer block 2358 * allocate a new pointer block 2359 * move some of the pointer into the new block 2360 * prepare for updating the parent block 2361 */ 2362 for (;;) /* do this twice when splitting block 1 */ 2363 { 2364 hp_new = ml_new_ptr(mfp); 2365 if (hp_new == NULL) /* TODO: try to fix tree */ 2366 return FAIL; 2367 pp_new = (PTR_BL *)(hp_new->bh_data); 2368 2369 if (hp->bh_bnum != 1) 2370 break; 2371 2372 /* 2373 * if block 1 becomes full the tree is given an extra level 2374 * The pointers from block 1 are moved into the new block. 2375 * block 1 is updated to point to the new block 2376 * then continue to split the new block 2377 */ 2378 mch_memmove(pp_new, pp, (size_t)page_size); 2379 pp->pb_count = 1; 2380 pp->pb_pointer[0].pe_bnum = hp_new->bh_bnum; 2381 pp->pb_pointer[0].pe_line_count = buf->b_ml.ml_line_count; 2382 pp->pb_pointer[0].pe_old_lnum = 1; 2383 pp->pb_pointer[0].pe_page_count = 1; 2384 mf_put(mfp, hp, TRUE, FALSE); /* release block 1 */ 2385 hp = hp_new; /* new block is to be split */ 2386 pp = pp_new; 2387 CHECK(stack_idx != 0, _("stack_idx should be 0")); 2388 ip->ip_index = 0; 2389 ++stack_idx; /* do block 1 again later */ 2390 } 2391 /* 2392 * move the pointers after the current one to the new block 2393 * If there are none, the new entry will be in the new block. 2394 */ 2395 total_moved = pp->pb_count - pb_idx - 1; 2396 if (total_moved) 2397 { 2398 mch_memmove(&pp_new->pb_pointer[0], 2399 &pp->pb_pointer[pb_idx + 1], 2400 (size_t)(total_moved) * sizeof(PTR_EN)); 2401 pp_new->pb_count = total_moved; 2402 pp->pb_count -= total_moved - 1; 2403 pp->pb_pointer[pb_idx + 1].pe_bnum = bnum_right; 2404 pp->pb_pointer[pb_idx + 1].pe_line_count = line_count_right; 2405 pp->pb_pointer[pb_idx + 1].pe_page_count = page_count_right; 2406 if (lnum_right) 2407 pp->pb_pointer[pb_idx + 1].pe_old_lnum = lnum_right; 2408 } 2409 else 2410 { 2411 pp_new->pb_count = 1; 2412 pp_new->pb_pointer[0].pe_bnum = bnum_right; 2413 pp_new->pb_pointer[0].pe_line_count = line_count_right; 2414 pp_new->pb_pointer[0].pe_page_count = page_count_right; 2415 pp_new->pb_pointer[0].pe_old_lnum = lnum_right; 2416 } 2417 pp->pb_pointer[pb_idx].pe_bnum = bnum_left; 2418 pp->pb_pointer[pb_idx].pe_line_count = line_count_left; 2419 pp->pb_pointer[pb_idx].pe_page_count = page_count_left; 2420 if (lnum_left) 2421 pp->pb_pointer[pb_idx].pe_old_lnum = lnum_left; 2422 lnum_left = 0; 2423 lnum_right = 0; 2424 2425 /* 2426 * recompute line counts 2427 */ 2428 line_count_right = 0; 2429 for (i = 0; i < (int)pp_new->pb_count; ++i) 2430 line_count_right += pp_new->pb_pointer[i].pe_line_count; 2431 line_count_left = 0; 2432 for (i = 0; i < (int)pp->pb_count; ++i) 2433 line_count_left += pp->pb_pointer[i].pe_line_count; 2434 2435 bnum_left = hp->bh_bnum; 2436 bnum_right = hp_new->bh_bnum; 2437 page_count_left = 1; 2438 page_count_right = 1; 2439 mf_put(mfp, hp, TRUE, FALSE); 2440 mf_put(mfp, hp_new, TRUE, FALSE); 2441 } 2442 } 2443 2444 /* 2445 * Safety check: fallen out of for loop? 2446 */ 2447 if (stack_idx < 0) 2448 { 2449 EMSG(_("E318: Updated too many blocks?")); 2450 buf->b_ml.ml_stack_top = 0; /* invalidate stack */ 2451 } 2452 } 2453 2454 #ifdef FEAT_BYTEOFF 2455 /* The line was inserted below 'lnum' */ 2456 ml_updatechunk(buf, lnum + 1, (long)len, ML_CHNK_ADDLINE); 2457 #endif 2458 #ifdef FEAT_NETBEANS_INTG 2459 if (usingNetbeans) 2460 { 2461 if (STRLEN(line) > 0) 2462 netbeans_inserted(buf, lnum+1, (colnr_T)0, 0, line, STRLEN(line)); 2463 netbeans_inserted(buf, lnum+1, (colnr_T)STRLEN(line), 0, 2464 (char_u *)"\n", 1); 2465 } 2466 #endif 2467 return OK; 2468 } 2469 2470 /* 2471 * replace line lnum, with buffering, in current buffer 2472 * 2473 * If copy is TRUE, make a copy of the line, otherwise the line has been 2474 * copied to allocated memory already. 2475 * 2476 * Check: The caller of this function should probably also call 2477 * changed_lines(), unless update_screen(NOT_VALID) is used. 2478 * 2479 * return FAIL for failure, OK otherwise 2480 */ 2481 int 2482 ml_replace(lnum, line, copy) 2483 linenr_T lnum; 2484 char_u *line; 2485 int copy; 2486 { 2487 if (line == NULL) /* just checking... */ 2488 return FAIL; 2489 2490 /* When starting up, we might still need to create the memfile */ 2491 if (curbuf->b_ml.ml_mfp == NULL && open_buffer(FALSE, NULL) == FAIL) 2492 return FAIL; 2493 2494 if (copy && (line = vim_strsave(line)) == NULL) /* allocate memory */ 2495 return FAIL; 2496 #ifdef FEAT_NETBEANS_INTG 2497 if (usingNetbeans) 2498 { 2499 netbeans_removed(curbuf, lnum, 0, (long)STRLEN(ml_get(lnum))); 2500 netbeans_inserted(curbuf, lnum, 0, 0, line, STRLEN(line)); 2501 } 2502 #endif 2503 if (curbuf->b_ml.ml_line_lnum != lnum) /* other line buffered */ 2504 ml_flush_line(curbuf); /* flush it */ 2505 else if (curbuf->b_ml.ml_flags & ML_LINE_DIRTY) /* same line allocated */ 2506 vim_free(curbuf->b_ml.ml_line_ptr); /* free it */ 2507 curbuf->b_ml.ml_line_ptr = line; 2508 curbuf->b_ml.ml_line_lnum = lnum; 2509 curbuf->b_ml.ml_flags = (curbuf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY; 2510 2511 return OK; 2512 } 2513 2514 /* 2515 * delete line 'lnum' 2516 * 2517 * Check: The caller of this function should probably also call 2518 * deleted_lines() after this. 2519 * 2520 * return FAIL for failure, OK otherwise 2521 */ 2522 int 2523 ml_delete(lnum, message) 2524 linenr_T lnum; 2525 int message; 2526 { 2527 ml_flush_line(curbuf); 2528 return ml_delete_int(curbuf, lnum, message); 2529 } 2530 2531 static int 2532 ml_delete_int(buf, lnum, message) 2533 buf_T *buf; 2534 linenr_T lnum; 2535 int message; 2536 { 2537 bhdr_T *hp; 2538 memfile_T *mfp; 2539 DATA_BL *dp; 2540 PTR_BL *pp; 2541 infoptr_T *ip; 2542 int count; /* number of entries in block */ 2543 int idx; 2544 int stack_idx; 2545 int text_start; 2546 int line_start; 2547 long line_size; 2548 int i; 2549 2550 if (lnum < 1 || lnum > buf->b_ml.ml_line_count) 2551 return FAIL; 2552 2553 if (lowest_marked && lowest_marked > lnum) 2554 lowest_marked--; 2555 2556 /* 2557 * If the file becomes empty the last line is replaced by an empty line. 2558 */ 2559 if (buf->b_ml.ml_line_count == 1) /* file becomes empty */ 2560 { 2561 if (message 2562 #ifdef FEAT_NETBEANS_INTG 2563 && !netbeansSuppressNoLines 2564 #endif 2565 ) 2566 { 2567 set_keep_msg((char_u *)_(no_lines_msg)); 2568 keep_msg_attr = 0; 2569 } 2570 /* FEAT_BYTEOFF already handled in there, dont worry 'bout it below */ 2571 i = ml_replace((linenr_T)1, (char_u *)"", TRUE); 2572 buf->b_ml.ml_flags |= ML_EMPTY; 2573 2574 return i; 2575 } 2576 2577 /* 2578 * find the data block containing the line 2579 * This also fills the stack with the blocks from the root to the data block 2580 * This also releases any locked block. 2581 */ 2582 mfp = buf->b_ml.ml_mfp; 2583 if (mfp == NULL) 2584 return FAIL; 2585 2586 if ((hp = ml_find_line(buf, lnum, ML_DELETE)) == NULL) 2587 return FAIL; 2588 2589 dp = (DATA_BL *)(hp->bh_data); 2590 /* compute line count before the delete */ 2591 count = (long)(buf->b_ml.ml_locked_high) 2592 - (long)(buf->b_ml.ml_locked_low) + 2; 2593 idx = lnum - buf->b_ml.ml_locked_low; 2594 2595 --buf->b_ml.ml_line_count; 2596 2597 line_start = ((dp->db_index[idx]) & DB_INDEX_MASK); 2598 if (idx == 0) /* first line in block, text at the end */ 2599 line_size = dp->db_txt_end - line_start; 2600 else 2601 line_size = ((dp->db_index[idx - 1]) & DB_INDEX_MASK) - line_start; 2602 2603 #ifdef FEAT_NETBEANS_INTG 2604 if (usingNetbeans) 2605 netbeans_removed(buf, lnum, 0, line_size); 2606 #endif 2607 2608 /* 2609 * special case: If there is only one line in the data block it becomes empty. 2610 * Then we have to remove the entry, pointing to this data block, from the 2611 * pointer block. If this pointer block also becomes empty, we go up another 2612 * block, and so on, up to the root if necessary. 2613 * The line counts in the pointer blocks have already been adjusted by 2614 * ml_find_line(). 2615 */ 2616 if (count == 1) 2617 { 2618 mf_free(mfp, hp); /* free the data block */ 2619 buf->b_ml.ml_locked = NULL; 2620 2621 for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; --stack_idx) 2622 { 2623 buf->b_ml.ml_stack_top = 0; /* stack is invalid when failing */ 2624 ip = &(buf->b_ml.ml_stack[stack_idx]); 2625 idx = ip->ip_index; 2626 if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) 2627 return FAIL; 2628 pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */ 2629 if (pp->pb_id != PTR_ID) 2630 { 2631 EMSG(_("E317: pointer block id wrong 4")); 2632 mf_put(mfp, hp, FALSE, FALSE); 2633 return FAIL; 2634 } 2635 count = --(pp->pb_count); 2636 if (count == 0) /* the pointer block becomes empty! */ 2637 mf_free(mfp, hp); 2638 else 2639 { 2640 if (count != idx) /* move entries after the deleted one */ 2641 mch_memmove(&pp->pb_pointer[idx], &pp->pb_pointer[idx + 1], 2642 (size_t)(count - idx) * sizeof(PTR_EN)); 2643 mf_put(mfp, hp, TRUE, FALSE); 2644 2645 buf->b_ml.ml_stack_top = stack_idx; /* truncate stack */ 2646 /* fix line count for rest of blocks in the stack */ 2647 if (buf->b_ml.ml_locked_lineadd) 2648 { 2649 ml_lineadd(buf, buf->b_ml.ml_locked_lineadd); 2650 buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high += 2651 buf->b_ml.ml_locked_lineadd; 2652 } 2653 ++(buf->b_ml.ml_stack_top); 2654 2655 break; 2656 } 2657 } 2658 CHECK(stack_idx < 0, _("deleted block 1?")); 2659 } 2660 else 2661 { 2662 /* 2663 * delete the text by moving the next lines forwards 2664 */ 2665 text_start = dp->db_txt_start; 2666 mch_memmove((char *)dp + text_start + line_size, 2667 (char *)dp + text_start, (size_t)(line_start - text_start)); 2668 2669 /* 2670 * delete the index by moving the next indexes backwards 2671 * Adjust the indexes for the text movement. 2672 */ 2673 for (i = idx; i < count - 1; ++i) 2674 dp->db_index[i] = dp->db_index[i + 1] + line_size; 2675 2676 dp->db_free += line_size + INDEX_SIZE; 2677 dp->db_txt_start += line_size; 2678 --(dp->db_line_count); 2679 2680 /* 2681 * mark the block dirty and make sure it is in the file (for recovery) 2682 */ 2683 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); 2684 } 2685 2686 #ifdef FEAT_BYTEOFF 2687 ml_updatechunk(buf, lnum, line_size, ML_CHNK_DELLINE); 2688 #endif 2689 return OK; 2690 } 2691 2692 /* 2693 * set the B_MARKED flag for line 'lnum' 2694 */ 2695 void 2696 ml_setmarked(lnum) 2697 linenr_T lnum; 2698 { 2699 bhdr_T *hp; 2700 DATA_BL *dp; 2701 /* invalid line number */ 2702 if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count 2703 || curbuf->b_ml.ml_mfp == NULL) 2704 return; /* give error message? */ 2705 2706 if (lowest_marked == 0 || lowest_marked > lnum) 2707 lowest_marked = lnum; 2708 2709 /* 2710 * find the data block containing the line 2711 * This also fills the stack with the blocks from the root to the data block 2712 * This also releases any locked block. 2713 */ 2714 if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) 2715 return; /* give error message? */ 2716 2717 dp = (DATA_BL *)(hp->bh_data); 2718 dp->db_index[lnum - curbuf->b_ml.ml_locked_low] |= DB_MARKED; 2719 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY; 2720 } 2721 2722 /* 2723 * find the first line with its B_MARKED flag set 2724 */ 2725 linenr_T 2726 ml_firstmarked() 2727 { 2728 bhdr_T *hp; 2729 DATA_BL *dp; 2730 linenr_T lnum; 2731 int i; 2732 2733 if (curbuf->b_ml.ml_mfp == NULL) 2734 return (linenr_T) 0; 2735 2736 /* 2737 * The search starts with lowest_marked line. This is the last line where 2738 * a mark was found, adjusted by inserting/deleting lines. 2739 */ 2740 for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; ) 2741 { 2742 /* 2743 * Find the data block containing the line. 2744 * This also fills the stack with the blocks from the root to the data 2745 * block This also releases any locked block. 2746 */ 2747 if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) 2748 return (linenr_T)0; /* give error message? */ 2749 2750 dp = (DATA_BL *)(hp->bh_data); 2751 2752 for (i = lnum - curbuf->b_ml.ml_locked_low; 2753 lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum) 2754 if ((dp->db_index[i]) & DB_MARKED) 2755 { 2756 (dp->db_index[i]) &= DB_INDEX_MASK; 2757 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY; 2758 lowest_marked = lnum + 1; 2759 return lnum; 2760 } 2761 } 2762 2763 return (linenr_T) 0; 2764 } 2765 2766 #if 0 /* not used */ 2767 /* 2768 * return TRUE if line 'lnum' has a mark 2769 */ 2770 int 2771 ml_has_mark(lnum) 2772 linenr_T lnum; 2773 { 2774 bhdr_T *hp; 2775 DATA_BL *dp; 2776 2777 if (curbuf->b_ml.ml_mfp == NULL 2778 || (hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) 2779 return FALSE; 2780 2781 dp = (DATA_BL *)(hp->bh_data); 2782 return (int)((dp->db_index[lnum - curbuf->b_ml.ml_locked_low]) & DB_MARKED); 2783 } 2784 #endif 2785 2786 /* 2787 * clear all DB_MARKED flags 2788 */ 2789 void 2790 ml_clearmarked() 2791 { 2792 bhdr_T *hp; 2793 DATA_BL *dp; 2794 linenr_T lnum; 2795 int i; 2796 2797 if (curbuf->b_ml.ml_mfp == NULL) /* nothing to do */ 2798 return; 2799 2800 /* 2801 * The search starts with line lowest_marked. 2802 */ 2803 for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; ) 2804 { 2805 /* 2806 * Find the data block containing the line. 2807 * This also fills the stack with the blocks from the root to the data 2808 * block and releases any locked block. 2809 */ 2810 if ((hp = ml_find_line(curbuf, lnum, ML_FIND)) == NULL) 2811 return; /* give error message? */ 2812 2813 dp = (DATA_BL *)(hp->bh_data); 2814 2815 for (i = lnum - curbuf->b_ml.ml_locked_low; 2816 lnum <= curbuf->b_ml.ml_locked_high; ++i, ++lnum) 2817 if ((dp->db_index[i]) & DB_MARKED) 2818 { 2819 (dp->db_index[i]) &= DB_INDEX_MASK; 2820 curbuf->b_ml.ml_flags |= ML_LOCKED_DIRTY; 2821 } 2822 } 2823 2824 lowest_marked = 0; 2825 return; 2826 } 2827 2828 /* 2829 * flush ml_line if necessary 2830 */ 2831 static void 2832 ml_flush_line(buf) 2833 buf_T *buf; 2834 { 2835 bhdr_T *hp; 2836 DATA_BL *dp; 2837 linenr_T lnum; 2838 char_u *new_line; 2839 char_u *old_line; 2840 colnr_T new_len; 2841 int old_len; 2842 int extra; 2843 int idx; 2844 int start; 2845 int count; 2846 int i; 2847 2848 if (buf->b_ml.ml_line_lnum == 0 || buf->b_ml.ml_mfp == NULL) 2849 return; /* nothing to do */ 2850 2851 if (buf->b_ml.ml_flags & ML_LINE_DIRTY) 2852 { 2853 lnum = buf->b_ml.ml_line_lnum; 2854 new_line = buf->b_ml.ml_line_ptr; 2855 2856 hp = ml_find_line(buf, lnum, ML_FIND); 2857 if (hp == NULL) 2858 EMSGN(_("E320: Cannot find line %ld"), lnum); 2859 else 2860 { 2861 dp = (DATA_BL *)(hp->bh_data); 2862 idx = lnum - buf->b_ml.ml_locked_low; 2863 start = ((dp->db_index[idx]) & DB_INDEX_MASK); 2864 old_line = (char_u *)dp + start; 2865 if (idx == 0) /* line is last in block */ 2866 old_len = dp->db_txt_end - start; 2867 else /* text of previous line follows */ 2868 old_len = (dp->db_index[idx - 1] & DB_INDEX_MASK) - start; 2869 new_len = (colnr_T)STRLEN(new_line) + 1; 2870 extra = new_len - old_len; /* negative if lines gets smaller */ 2871 2872 /* 2873 * if new line fits in data block, replace directly 2874 */ 2875 if ((int)dp->db_free >= extra) 2876 { 2877 /* if the length changes and there are following lines */ 2878 count = buf->b_ml.ml_locked_high - buf->b_ml.ml_locked_low + 1; 2879 if (extra != 0 && idx < count - 1) 2880 { 2881 /* move text of following lines */ 2882 mch_memmove((char *)dp + dp->db_txt_start - extra, 2883 (char *)dp + dp->db_txt_start, 2884 (size_t)(start - dp->db_txt_start)); 2885 2886 /* adjust pointers of this and following lines */ 2887 for (i = idx + 1; i < count; ++i) 2888 dp->db_index[i] -= extra; 2889 } 2890 dp->db_index[idx] -= extra; 2891 2892 /* adjust free space */ 2893 dp->db_free -= extra; 2894 dp->db_txt_start -= extra; 2895 2896 /* copy new line into the data block */ 2897 mch_memmove(old_line - extra, new_line, (size_t)new_len); 2898 buf->b_ml.ml_flags |= (ML_LOCKED_DIRTY | ML_LOCKED_POS); 2899 #ifdef FEAT_BYTEOFF 2900 /* The else case is already covered by the insert and delete */ 2901 ml_updatechunk(buf, lnum, (long)extra, ML_CHNK_UPDLINE); 2902 #endif 2903 } 2904 else 2905 { 2906 /* 2907 * Cannot do it in one data block: Delete and append. 2908 * Append first, because ml_delete_int() cannot delete the 2909 * last line in a buffer, which causes trouble for a buffer 2910 * that has only one line. 2911 * Don't forget to copy the mark! 2912 */ 2913 /* How about handling errors??? */ 2914 (void)ml_append_int(buf, lnum, new_line, new_len, FALSE, 2915 (dp->db_index[idx] & DB_MARKED)); 2916 (void)ml_delete_int(buf, lnum, FALSE); 2917 } 2918 } 2919 vim_free(new_line); 2920 } 2921 2922 buf->b_ml.ml_line_lnum = 0; 2923 } 2924 2925 /* 2926 * create a new, empty, data block 2927 */ 2928 static bhdr_T * 2929 ml_new_data(mfp, negative, page_count) 2930 memfile_T *mfp; 2931 int negative; 2932 int page_count; 2933 { 2934 bhdr_T *hp; 2935 DATA_BL *dp; 2936 2937 if ((hp = mf_new(mfp, negative, page_count)) == NULL) 2938 return NULL; 2939 2940 dp = (DATA_BL *)(hp->bh_data); 2941 dp->db_id = DATA_ID; 2942 dp->db_txt_start = dp->db_txt_end = page_count * mfp->mf_page_size; 2943 dp->db_free = dp->db_txt_start - HEADER_SIZE; 2944 dp->db_line_count = 0; 2945 2946 return hp; 2947 } 2948 2949 /* 2950 * create a new, empty, pointer block 2951 */ 2952 static bhdr_T * 2953 ml_new_ptr(mfp) 2954 memfile_T *mfp; 2955 { 2956 bhdr_T *hp; 2957 PTR_BL *pp; 2958 2959 if ((hp = mf_new(mfp, FALSE, 1)) == NULL) 2960 return NULL; 2961 2962 pp = (PTR_BL *)(hp->bh_data); 2963 pp->pb_id = PTR_ID; 2964 pp->pb_count = 0; 2965 pp->pb_count_max = (short_u)((mfp->mf_page_size - sizeof(PTR_BL)) / sizeof(PTR_EN) + 1); 2966 2967 return hp; 2968 } 2969 2970 /* 2971 * lookup line 'lnum' in a memline 2972 * 2973 * action: if ML_DELETE or ML_INSERT the line count is updated while searching 2974 * if ML_FLUSH only flush a locked block 2975 * if ML_FIND just find the line 2976 * 2977 * If the block was found it is locked and put in ml_locked. 2978 * The stack is updated to lead to the locked block. The ip_high field in 2979 * the stack is updated to reflect the last line in the block AFTER the 2980 * insert or delete, also if the pointer block has not been updated yet. But 2981 * if if ml_locked != NULL ml_locked_lineadd must be added to ip_high. 2982 * 2983 * return: NULL for failure, pointer to block header otherwise 2984 */ 2985 static bhdr_T * 2986 ml_find_line(buf, lnum, action) 2987 buf_T *buf; 2988 linenr_T lnum; 2989 int action; 2990 { 2991 DATA_BL *dp; 2992 PTR_BL *pp; 2993 infoptr_T *ip; 2994 bhdr_T *hp; 2995 memfile_T *mfp; 2996 linenr_T t; 2997 blocknr_T bnum, bnum2; 2998 int dirty; 2999 linenr_T low, high; 3000 int top; 3001 int page_count; 3002 int idx; 3003 3004 mfp = buf->b_ml.ml_mfp; 3005 3006 /* 3007 * If there is a locked block check if the wanted line is in it. 3008 * If not, flush and release the locked block. 3009 * Don't do this for ML_INSERT_SAME, because the stack need to be updated. 3010 * Don't do this for ML_FLUSH, because we want to flush the locked block. 3011 */ 3012 if (buf->b_ml.ml_locked) 3013 { 3014 if (ML_SIMPLE(action) && buf->b_ml.ml_locked_low <= lnum 3015 && buf->b_ml.ml_locked_high >= lnum) 3016 { 3017 /* remember to update pointer blocks and stack later */ 3018 if (action == ML_INSERT) 3019 { 3020 ++(buf->b_ml.ml_locked_lineadd); 3021 ++(buf->b_ml.ml_locked_high); 3022 } 3023 else if (action == ML_DELETE) 3024 { 3025 --(buf->b_ml.ml_locked_lineadd); 3026 --(buf->b_ml.ml_locked_high); 3027 } 3028 return (buf->b_ml.ml_locked); 3029 } 3030 3031 mf_put(mfp, buf->b_ml.ml_locked, buf->b_ml.ml_flags & ML_LOCKED_DIRTY, 3032 buf->b_ml.ml_flags & ML_LOCKED_POS); 3033 buf->b_ml.ml_locked = NULL; 3034 3035 /* 3036 * if lines have been added or deleted in the locked block, need to 3037 * update the line count in pointer blocks 3038 */ 3039 if (buf->b_ml.ml_locked_lineadd) 3040 ml_lineadd(buf, buf->b_ml.ml_locked_lineadd); 3041 } 3042 3043 if (action == ML_FLUSH) /* nothing else to do */ 3044 return NULL; 3045 3046 bnum = 1; /* start at the root of the tree */ 3047 page_count = 1; 3048 low = 1; 3049 high = buf->b_ml.ml_line_count; 3050 3051 if (action == ML_FIND) /* first try stack entries */ 3052 { 3053 for (top = buf->b_ml.ml_stack_top - 1; top >= 0; --top) 3054 { 3055 ip = &(buf->b_ml.ml_stack[top]); 3056 if (ip->ip_low <= lnum && ip->ip_high >= lnum) 3057 { 3058 bnum = ip->ip_bnum; 3059 low = ip->ip_low; 3060 high = ip->ip_high; 3061 buf->b_ml.ml_stack_top = top; /* truncate stack at prev entry */ 3062 break; 3063 } 3064 } 3065 if (top < 0) 3066 buf->b_ml.ml_stack_top = 0; /* not found, start at the root */ 3067 } 3068 else /* ML_DELETE or ML_INSERT */ 3069 buf->b_ml.ml_stack_top = 0; /* start at the root */ 3070 3071 /* 3072 * search downwards in the tree until a data block is found 3073 */ 3074 for (;;) 3075 { 3076 if ((hp = mf_get(mfp, bnum, page_count)) == NULL) 3077 goto error_noblock; 3078 3079 /* 3080 * update high for insert/delete 3081 */ 3082 if (action == ML_INSERT) 3083 ++high; 3084 else if (action == ML_DELETE) 3085 --high; 3086 3087 dp = (DATA_BL *)(hp->bh_data); 3088 if (dp->db_id == DATA_ID) /* data block */ 3089 { 3090 buf->b_ml.ml_locked = hp; 3091 buf->b_ml.ml_locked_low = low; 3092 buf->b_ml.ml_locked_high = high; 3093 buf->b_ml.ml_locked_lineadd = 0; 3094 buf->b_ml.ml_flags &= ~(ML_LOCKED_DIRTY | ML_LOCKED_POS); 3095 return hp; 3096 } 3097 3098 pp = (PTR_BL *)(dp); /* must be pointer block */ 3099 if (pp->pb_id != PTR_ID) 3100 { 3101 EMSG(_("E317: pointer block id wrong")); 3102 goto error_block; 3103 } 3104 3105 if ((top = ml_add_stack(buf)) < 0) /* add new entry to stack */ 3106 goto error_block; 3107 ip = &(buf->b_ml.ml_stack[top]); 3108 ip->ip_bnum = bnum; 3109 ip->ip_low = low; 3110 ip->ip_high = high; 3111 ip->ip_index = -1; /* index not known yet */ 3112 3113 dirty = FALSE; 3114 for (idx = 0; idx < (int)pp->pb_count; ++idx) 3115 { 3116 t = pp->pb_pointer[idx].pe_line_count; 3117 CHECK(t == 0, _("pe_line_count is zero")); 3118 if ((low += t) > lnum) 3119 { 3120 ip->ip_index = idx; 3121 bnum = pp->pb_pointer[idx].pe_bnum; 3122 page_count = pp->pb_pointer[idx].pe_page_count; 3123 high = low - 1; 3124 low -= t; 3125 3126 /* 3127 * a negative block number may have been changed 3128 */ 3129 if (bnum < 0) 3130 { 3131 bnum2 = mf_trans_del(mfp, bnum); 3132 if (bnum != bnum2) 3133 { 3134 bnum = bnum2; 3135 pp->pb_pointer[idx].pe_bnum = bnum; 3136 dirty = TRUE; 3137 } 3138 } 3139 3140 break; 3141 } 3142 } 3143 if (idx >= (int)pp->pb_count) /* past the end: something wrong! */ 3144 { 3145 if (lnum > buf->b_ml.ml_line_count) 3146 EMSGN(_("E322: line number out of range: %ld past the end"), 3147 lnum - buf->b_ml.ml_line_count); 3148 3149 else 3150 EMSGN(_("E323: line count wrong in block %ld"), bnum); 3151 goto error_block; 3152 } 3153 if (action == ML_DELETE) 3154 { 3155 pp->pb_pointer[idx].pe_line_count--; 3156 dirty = TRUE; 3157 } 3158 else if (action == ML_INSERT) 3159 { 3160 pp->pb_pointer[idx].pe_line_count++; 3161 dirty = TRUE; 3162 } 3163 mf_put(mfp, hp, dirty, FALSE); 3164 } 3165 3166 error_block: 3167 mf_put(mfp, hp, FALSE, FALSE); 3168 error_noblock: 3169 /* 3170 * If action is ML_DELETE or ML_INSERT we have to correct the tree for 3171 * the incremented/decremented line counts, because there won't be a line 3172 * inserted/deleted after all. 3173 */ 3174 if (action == ML_DELETE) 3175 ml_lineadd(buf, 1); 3176 else if (action == ML_INSERT) 3177 ml_lineadd(buf, -1); 3178 buf->b_ml.ml_stack_top = 0; 3179 return NULL; 3180 } 3181 3182 /* 3183 * add an entry to the info pointer stack 3184 * 3185 * return -1 for failure, number of the new entry otherwise 3186 */ 3187 static int 3188 ml_add_stack(buf) 3189 buf_T *buf; 3190 { 3191 int top; 3192 infoptr_T *newstack; 3193 3194 top = buf->b_ml.ml_stack_top; 3195 3196 /* may have to increase the stack size */ 3197 if (top == buf->b_ml.ml_stack_size) 3198 { 3199 CHECK(top > 0, _("Stack size increases")); /* more than 5 levels??? */ 3200 3201 newstack = (infoptr_T *)alloc((unsigned)sizeof(infoptr_T) * 3202 (buf->b_ml.ml_stack_size + STACK_INCR)); 3203 if (newstack == NULL) 3204 return -1; 3205 mch_memmove(newstack, buf->b_ml.ml_stack, (size_t)top * sizeof(infoptr_T)); 3206 vim_free(buf->b_ml.ml_stack); 3207 buf->b_ml.ml_stack = newstack; 3208 buf->b_ml.ml_stack_size += STACK_INCR; 3209 } 3210 3211 buf->b_ml.ml_stack_top++; 3212 return top; 3213 } 3214 3215 /* 3216 * Update the pointer blocks on the stack for inserted/deleted lines. 3217 * The stack itself is also updated. 3218 * 3219 * When a insert/delete line action fails, the line is not inserted/deleted, 3220 * but the pointer blocks have already been updated. That is fixed here by 3221 * walking through the stack. 3222 * 3223 * Count is the number of lines added, negative if lines have been deleted. 3224 */ 3225 static void 3226 ml_lineadd(buf, count) 3227 buf_T *buf; 3228 int count; 3229 { 3230 int idx; 3231 infoptr_T *ip; 3232 PTR_BL *pp; 3233 memfile_T *mfp = buf->b_ml.ml_mfp; 3234 bhdr_T *hp; 3235 3236 for (idx = buf->b_ml.ml_stack_top - 1; idx >= 0; --idx) 3237 { 3238 ip = &(buf->b_ml.ml_stack[idx]); 3239 if ((hp = mf_get(mfp, ip->ip_bnum, 1)) == NULL) 3240 break; 3241 pp = (PTR_BL *)(hp->bh_data); /* must be pointer block */ 3242 if (pp->pb_id != PTR_ID) 3243 { 3244 mf_put(mfp, hp, FALSE, FALSE); 3245 EMSG(_("E317: pointer block id wrong 2")); 3246 break; 3247 } 3248 pp->pb_pointer[ip->ip_index].pe_line_count += count; 3249 ip->ip_high += count; 3250 mf_put(mfp, hp, TRUE, FALSE); 3251 } 3252 } 3253 3254 /* 3255 * make swap file name out of the file name and a directory name 3256 */ 3257 static char_u * 3258 makeswapname(buf, dir_name) 3259 buf_T *buf; 3260 char_u *dir_name; 3261 { 3262 char_u *r, *s; 3263 3264 #if defined(UNIX) || defined(WIN3264) /* Need _very_ long file names */ 3265 s = dir_name + STRLEN(dir_name); 3266 if (vim_ispathsep(s[-1]) && s[-1] == s[-2]) 3267 { /* Ends with '//', Use Full path */ 3268 r = NULL; 3269 if ((s = make_percent_swname(dir_name, buf->b_fname)) != NULL) 3270 { 3271 r = modname(s, (char_u *)".swp", FALSE); 3272 vim_free(s); 3273 } 3274 return r; 3275 } 3276 #endif 3277 3278 r = buf_modname( 3279 #ifdef SHORT_FNAME 3280 TRUE, 3281 #else 3282 (buf->b_p_sn || buf->b_shortname), 3283 #endif 3284 #ifdef RISCOS 3285 /* Avoid problems if fname has special chars, eg <Wimp$Scrap> */ 3286 buf->b_ffname, 3287 #else 3288 buf->b_fname, 3289 #endif 3290 (char_u *) 3291 #if defined(VMS) || defined(RISCOS) 3292 "_swp", 3293 #else 3294 ".swp", 3295 #endif 3296 #ifdef SHORT_FNAME /* always 8.3 file name */ 3297 FALSE 3298 #else 3299 /* Prepend a '.' to the swap file name for the current directory. */ 3300 dir_name[0] == '.' && dir_name[1] == NUL 3301 #endif 3302 ); 3303 if (r == NULL) /* out of memory */ 3304 return NULL; 3305 3306 s = get_file_in_dir(r, dir_name); 3307 vim_free(r); 3308 return s; 3309 } 3310 3311 /* 3312 * Get file name to use for swap file or backup file. 3313 * Use the name of the edited file "fname" and an entry in the 'dir' or 'bdir' 3314 * option "dname". 3315 * - If "dname" is ".", return "fname" (swap file in dir of file). 3316 * - If "dname" starts with "./", insert "dname" in "fname" (swap file 3317 * relative to dir of file). 3318 * - Otherwise, prepend "dname" to the tail of "fname" (swap file in specific 3319 * dir). 3320 * 3321 * The return value is an allocated string and can be NULL. 3322 */ 3323 char_u * 3324 get_file_in_dir(fname, dname) 3325 char_u *fname; 3326 char_u *dname; /* don't use "dirname", it is a global for Alpha */ 3327 { 3328 char_u *t; 3329 char_u *tail; 3330 char_u *retval; 3331 int save_char; 3332 3333 tail = gettail(fname); 3334 3335 if (dname[0] == '.' && dname[1] == NUL) 3336 retval = vim_strsave(fname); 3337 else if (dname[0] == '.' && vim_ispathsep(dname[1])) 3338 { 3339 if (tail == fname) /* no path before file name */ 3340 retval = concat_fnames(dname + 2, tail, TRUE); 3341 else 3342 { 3343 save_char = *tail; 3344 *tail = NUL; 3345 t = concat_fnames(fname, dname + 2, TRUE); 3346 *tail = save_char; 3347 if (t == NULL) /* out of memory */ 3348 retval = NULL; 3349 else 3350 { 3351 retval = concat_fnames(t, tail, TRUE); 3352 vim_free(t); 3353 } 3354 } 3355 } 3356 else 3357 retval = concat_fnames(dname, tail, TRUE); 3358 3359 return retval; 3360 } 3361 3362 /* 3363 * Find out what name to use for the swap file for buffer 'buf'. 3364 * 3365 * Several names are tried to find one that does not exist 3366 * 3367 * Note: If BASENAMELEN is not correct, you will get error messages for 3368 * not being able to open the swapfile 3369 */ 3370 static char_u * 3371 findswapname(buf, dirp, old_fname) 3372 buf_T *buf; 3373 char_u **dirp; /* pointer to list of directories */ 3374 char_u *old_fname; /* don't give warning for this file name */ 3375 { 3376 char_u *fname; 3377 int n; 3378 time_t x, sx; 3379 char_u *dir_name; 3380 #ifdef AMIGA 3381 BPTR fh; 3382 #endif 3383 #ifndef SHORT_FNAME 3384 int r; 3385 #endif 3386 3387 #if !defined(SHORT_FNAME) \ 3388 && ((!defined(UNIX) && !defined(OS2)) || defined(ARCHIE)) 3389 # define CREATE_DUMMY_FILE 3390 FILE *dummyfd = NULL; 3391 3392 /* 3393 * If we start editing a new file, e.g. "test.doc", which resides on an MSDOS 3394 * compatible filesystem, it is possible that the file "test.doc.swp" which we 3395 * create will be exactly the same file. To avoid this problem we temporarily 3396 * create "test.doc". 3397 * Don't do this when the check below for a 8.3 file name is used. 3398 */ 3399 if (!(buf->b_p_sn || buf->b_shortname) && buf->b_fname != NULL 3400 && mch_getperm(buf->b_fname) < 0) 3401 dummyfd = mch_fopen((char *)buf->b_fname, "w"); 3402 #endif 3403 3404 /* 3405 * Isolate a directory name from *dirp and put it in dir_name. 3406 * First allocate some memory to put the directory name in. 3407 */ 3408 dir_name = alloc((unsigned)STRLEN(*dirp) + 1); 3409 if (dir_name != NULL) 3410 (void)copy_option_part(dirp, dir_name, 31000, ","); 3411 3412 /* 3413 * we try different names until we find one that does not exist yet 3414 */ 3415 if (dir_name == NULL) /* out of memory */ 3416 fname = NULL; 3417 else 3418 fname = makeswapname(buf, dir_name); 3419 3420 for (;;) 3421 { 3422 if (fname == NULL) /* must be out of memory */ 3423 break; 3424 if ((n = (int)STRLEN(fname)) == 0) /* safety check */ 3425 { 3426 vim_free(fname); 3427 fname = NULL; 3428 break; 3429 } 3430 #if (defined(UNIX) || defined(OS2)) && !defined(ARCHIE) && !defined(SHORT_FNAME) 3431 /* 3432 * Some systems have a MS-DOS compatible filesystem that use 8.3 character 3433 * file names. If this is the first try and the swap file name does not fit in 3434 * 8.3, detect if this is the case, set shortname and try again. 3435 */ 3436 if (fname[n - 2] == 'w' && fname[n - 1] == 'p' 3437 && !(buf->b_p_sn || buf->b_shortname)) 3438 { 3439 char_u *tail; 3440 char_u *fname2; 3441 struct stat s1, s2; 3442 int f1, f2; 3443 int created1 = FALSE, created2 = FALSE; 3444 int same = FALSE; 3445 3446 /* 3447 * Check if swapfile name does not fit in 8.3: 3448 * It either contains two dots, is longer than 8 chars, or starts 3449 * with a dot. 3450 */ 3451 tail = gettail(buf->b_fname); 3452 if ( vim_strchr(tail, '.') != NULL 3453 || STRLEN(tail) > (size_t)8 3454 || *gettail(fname) == '.') 3455 { 3456 fname2 = alloc(n + 2); 3457 if (fname2 != NULL) 3458 { 3459 STRCPY(fname2, fname); 3460 /* if fname == "xx.xx.swp", fname2 = "xx.xx.swx" 3461 * if fname == ".xx.swp", fname2 = ".xx.swpx" 3462 * if fname == "123456789.swp", fname2 = "12345678x.swp" 3463 */ 3464 if (vim_strchr(tail, '.') != NULL) 3465 fname2[n - 1] = 'x'; 3466 else if (*gettail(fname) == '.') 3467 { 3468 fname2[n] = 'x'; 3469 fname2[n + 1] = NUL; 3470 } 3471 else 3472 fname2[n - 5] += 1; 3473 /* 3474 * may need to create the files to be able to use mch_stat() 3475 */ 3476 f1 = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0); 3477 if (f1 < 0) 3478 { 3479 f1 = mch_open_rw((char *)fname, 3480 O_RDWR|O_CREAT|O_EXCL|O_EXTRA); 3481 #if defined(OS2) 3482 if (f1 < 0 && errno == ENOENT) 3483 same = TRUE; 3484 #endif 3485 created1 = TRUE; 3486 } 3487 if (f1 >= 0) 3488 { 3489 f2 = mch_open((char *)fname2, O_RDONLY | O_EXTRA, 0); 3490 if (f2 < 0) 3491 { 3492 f2 = mch_open_rw((char *)fname2, 3493 O_RDWR|O_CREAT|O_EXCL|O_EXTRA); 3494 created2 = TRUE; 3495 } 3496 if (f2 >= 0) 3497 { 3498 /* 3499 * Both files exist now. If mch_stat() returns the 3500 * same device and inode they are the same file. 3501 */ 3502 if (mch_fstat(f1, &s1) != -1 3503 && mch_fstat(f2, &s2) != -1 3504 && s1.st_dev == s2.st_dev 3505 && s1.st_ino == s2.st_ino) 3506 same = TRUE; 3507 close(f2); 3508 if (created2) 3509 mch_remove(fname2); 3510 } 3511 close(f1); 3512 if (created1) 3513 mch_remove(fname); 3514 } 3515 vim_free(fname2); 3516 if (same) 3517 { 3518 buf->b_shortname = TRUE; 3519 vim_free(fname); 3520 fname = makeswapname(buf, dir_name); 3521 continue; /* try again with b_shortname set */ 3522 } 3523 } 3524 } 3525 } 3526 #endif 3527 /* 3528 * check if the swapfile already exists 3529 */ 3530 if (mch_getperm(fname) < 0) /* it does not exist */ 3531 { 3532 #ifdef HAVE_LSTAT 3533 struct stat sb; 3534 3535 /* 3536 * Extra security check: When a swap file is a symbolic link, this 3537 * is most likely a symlink attack. 3538 */ 3539 if (mch_lstat((char *)fname, &sb) < 0) 3540 #else 3541 # ifdef AMIGA 3542 fh = Open((UBYTE *)fname, (long)MODE_NEWFILE); 3543 /* 3544 * on the Amiga mch_getperm() will return -1 when the file exists 3545 * but is being used by another program. This happens if you edit 3546 * a file twice. 3547 */ 3548 if (fh != (BPTR)NULL) /* can open file, OK */ 3549 { 3550 Close(fh); 3551 mch_remove(fname); 3552 break; 3553 } 3554 if (IoErr() != ERROR_OBJECT_IN_USE 3555 && IoErr() != ERROR_OBJECT_EXISTS) 3556 # endif 3557 #endif 3558 break; 3559 } 3560 3561 /* 3562 * A file name equal to old_fname is OK to use. 3563 */ 3564 if (old_fname != NULL && fnamecmp(fname, old_fname) == 0) 3565 break; 3566 3567 /* 3568 * get here when file already exists 3569 */ 3570 if (fname[n - 2] == 'w' && fname[n - 1] == 'p') /* first try */ 3571 { 3572 #ifndef SHORT_FNAME 3573 /* 3574 * on MS-DOS compatible filesystems (e.g. messydos) file.doc.swp 3575 * and file.doc are the same file. To guess if this problem is 3576 * present try if file.doc.swx exists. If it does, we set 3577 * buf->b_shortname and try file_doc.swp (dots replaced by 3578 * underscores for this file), and try again. If it doesn't we 3579 * assume that "file.doc.swp" already exists. 3580 */ 3581 if (!(buf->b_p_sn || buf->b_shortname)) /* not tried yet */ 3582 { 3583 fname[n - 1] = 'x'; 3584 r = mch_getperm(fname); /* try "file.swx" */ 3585 fname[n - 1] = 'p'; 3586 if (r >= 0) /* "file.swx" seems to exist */ 3587 { 3588 buf->b_shortname = TRUE; 3589 vim_free(fname); 3590 fname = makeswapname(buf, dir_name); 3591 continue; /* try again with '.' replaced with '_' */ 3592 } 3593 } 3594 #endif 3595 /* 3596 * If we get here the ".swp" file really exists. 3597 * Give an error message, unless recovering, no file name, we are 3598 * viewing a help file or when the path of the file is different 3599 * (happens when all .swp files are in one directory). 3600 */ 3601 if (!recoverymode && buf->b_fname != NULL && !buf->b_help) 3602 { 3603 int fd; 3604 struct block0 b0; 3605 int differ = FALSE; 3606 3607 /* 3608 * Try to read block 0 from the swap file to get the original 3609 * file name (and inode number). 3610 */ 3611 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0); 3612 if (fd >= 0) 3613 { 3614 if (read(fd, (char *)&b0, sizeof(b0)) == sizeof(b0)) 3615 { 3616 /* 3617 * The name in the swap file may be "~user/path/file". 3618 * Expand it first. 3619 */ 3620 expand_env(b0.b0_fname, NameBuff, MAXPATHL); 3621 #ifdef CHECK_INODE 3622 if (fnamecmp_ino(buf->b_ffname, NameBuff, 3623 char_to_long(b0.b0_ino))) 3624 differ = TRUE; 3625 #else 3626 if (fnamecmp(NameBuff, buf->b_ffname) != 0) 3627 differ = TRUE; 3628 #endif 3629 } 3630 close(fd); 3631 } 3632 #ifdef RISCOS 3633 else 3634 /* Can't open swap file, though it does exist. 3635 * Assume that the user is editing two files with 3636 * the same name in different directories. No error. 3637 */ 3638 differ = TRUE; 3639 #endif 3640 3641 /* give the ATTENTION message when there is an old swap file 3642 * for the current file, and the buffer was not recovered. */ 3643 if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED) 3644 && vim_strchr(p_shm, SHM_ATTENTION) == NULL) 3645 { 3646 struct stat st; 3647 #ifdef CREATE_DUMMY_FILE 3648 int did_use_dummy = FALSE; 3649 3650 /* Avoid getting a warning for the file being created 3651 * outside of Vim, it was created at the start of this 3652 * function. Delete the file now, because Vim might exit 3653 * here if the window is closed. */ 3654 if (dummyfd != NULL) 3655 { 3656 fclose(dummyfd); 3657 dummyfd = NULL; 3658 mch_remove(buf->b_fname); 3659 did_use_dummy = TRUE; 3660 } 3661 #endif 3662 #ifdef FEAT_GUI 3663 /* If we are supposed to start the GUI but it wasn't 3664 * completely started yet, start it now. This makes the 3665 * messages displayed in the Vim window when loading a 3666 * session from the .gvimrc file. */ 3667 if (gui.starting && !gui.in_use) 3668 gui_start(); 3669 #endif 3670 3671 #if (defined(UNIX) || defined(__EMX__) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)) 3672 process_still_running = FALSE; 3673 #endif 3674 ++no_wait_return; 3675 (void)EMSG(_("E325: ATTENTION")); 3676 MSG_PUTS(_("\nFound a swap file by the name \"")); 3677 msg_home_replace(fname); 3678 MSG_PUTS("\"\n"); 3679 sx = swapfile_info(fname); 3680 MSG_PUTS(_("While opening file \"")); 3681 msg_outtrans(buf->b_fname); 3682 MSG_PUTS("\"\n"); 3683 if (mch_stat((char *)buf->b_fname, &st) != -1) 3684 { 3685 MSG_PUTS(_(" dated: ")); 3686 x = st.st_mtime; /* Manx C can't do &st.st_mtime */ 3687 MSG_PUTS(ctime(&x)); 3688 if (sx != 0 && x > sx) 3689 MSG_PUTS(_(" NEWER than swap file!\n")); 3690 } 3691 /* Some of these messages are long to allow translation to 3692 * other languages. */ 3693 MSG_PUTS(_("\n(1) Another program may be editing the same file.\n If this is the case, be careful not to end up with two\n different instances of the same file when making changes.\n")); 3694 MSG_PUTS(_(" Quit, or continue with caution.\n")); 3695 MSG_PUTS(_("\n(2) An edit session for this file crashed.\n")); 3696 MSG_PUTS(_(" If this is the case, use \":recover\" or \"vim -r ")); 3697 msg_outtrans(buf->b_fname); 3698 MSG_PUTS(_("\"\n to recover the changes (see \":help recovery\").\n")); 3699 MSG_PUTS(_(" If you did this already, delete the swap file \"")); 3700 msg_outtrans(fname); 3701 MSG_PUTS(_("\"\n to avoid this message.\n")); 3702 cmdline_row = msg_row; 3703 --no_wait_return; 3704 3705 /* We don't want a 'q' typed at the more-prompt interrupt 3706 * loading a file. */ 3707 got_int = FALSE; 3708 3709 #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) 3710 if (swap_exists_action) 3711 { 3712 char_u *name; 3713 3714 name = alloc((unsigned)(STRLEN(fname) 3715 + STRLEN(_("Swap file \"")) 3716 + STRLEN(_("\" already exists!")) + 5)); 3717 if (name != NULL) 3718 { 3719 STRCPY(name, _("Swap file \"")); 3720 home_replace(NULL, fname, name + STRLEN(name), 3721 1000, TRUE); 3722 STRCAT(name, _("\" already exists!")); 3723 } 3724 switch (do_dialog(VIM_WARNING, 3725 (char_u *)_("VIM - ATTENTION"), 3726 name == NULL 3727 ? (char_u *)_("Swap file already exists!") 3728 : name, 3729 # if defined(UNIX) || defined(__EMX__) || defined(VMS) 3730 process_still_running 3731 ? (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort") : 3732 # endif 3733 (char_u *)_("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort\n&Delete it"), 1, NULL)) 3734 { 3735 case 1: 3736 buf->b_p_ro = TRUE; 3737 break; 3738 case 2: 3739 break; 3740 case 3: 3741 swap_exists_action = SEA_RECOVER; 3742 break; 3743 case 4: 3744 swap_exists_action = SEA_QUIT; 3745 break; 3746 case 5: 3747 swap_exists_action = SEA_QUIT; 3748 got_int = TRUE; 3749 break; 3750 case 6: 3751 mch_remove(fname); 3752 break; 3753 } 3754 vim_free(name); 3755 3756 /* pretend screen didn't scroll, need redraw anyway */ 3757 msg_scrolled = 0; 3758 redraw_all_later(NOT_VALID); 3759 3760 /* If the file was deleted this fname can be used. */ 3761 if (mch_getperm(fname) < 0) 3762 break; 3763 } 3764 else 3765 #endif 3766 { 3767 MSG_PUTS("\n"); 3768 need_wait_return = TRUE; /* call wait_return later */ 3769 } 3770 3771 #ifdef CREATE_DUMMY_FILE 3772 /* Going to try another name, need the dummy file again. */ 3773 if (did_use_dummy) 3774 dummyfd = mch_fopen((char *)buf->b_fname, "w"); 3775 #endif 3776 } 3777 } 3778 } 3779 3780 /* 3781 * Change the ".swp" extension to find another file that can be used. 3782 * First decrement the last char: ".swo", ".swn", etc. 3783 * If that still isn't enough decrement the last but one char: ".svz" 3784 * Can happen when editing many "No Name" buffers. 3785 */ 3786 if (fname[n - 1] == 'a') /* ".s?a" */ 3787 { 3788 if (fname[n - 2] == 'a') /* ".saa": tried enough, give up */ 3789 { 3790 EMSG(_("E326: Too many swap files found")); 3791 vim_free(fname); 3792 fname = NULL; 3793 break; 3794 } 3795 --fname[n - 2]; /* ".svz", ".suz", etc. */ 3796 fname[n - 1] = 'z' + 1; 3797 } 3798 --fname[n - 1]; /* ".swo", ".swn", etc. */ 3799 } 3800 3801 vim_free(dir_name); 3802 #ifdef CREATE_DUMMY_FILE 3803 if (dummyfd != NULL) /* file has been created temporarily */ 3804 { 3805 fclose(dummyfd); 3806 mch_remove(buf->b_fname); 3807 } 3808 #endif 3809 return fname; 3810 } 3811 3812 static int 3813 b0_magic_wrong(b0p) 3814 ZERO_BL *b0p; 3815 { 3816 return (b0p->b0_magic_long != (long)B0_MAGIC_LONG 3817 || b0p->b0_magic_int != (int)B0_MAGIC_INT 3818 || b0p->b0_magic_short != (short)B0_MAGIC_SHORT 3819 || b0p->b0_magic_char != B0_MAGIC_CHAR); 3820 } 3821 3822 #ifdef CHECK_INODE 3823 /* 3824 * Compare current file name with file name from swap file. 3825 * Try to use inode numbers when possible. 3826 * Return non-zero when files are different. 3827 * 3828 * When comparing file names a few things have to be taken into consideration: 3829 * - When working over a network the full path of a file depends on the host. 3830 * We check the inode number if possible. It is not 100% reliable though, 3831 * because the device number cannot be used over a network. 3832 * - When a file does not exist yet (editing a new file) there is no inode 3833 * number. 3834 * - The file name in a swap file may not be valid on the current host. The 3835 * "~user" form is used whenever possible to avoid this. 3836 * 3837 * This is getting complicated, let's make a table: 3838 * 3839 * ino_c ino_s fname_c fname_s differ = 3840 * 3841 * both files exist -> compare inode numbers: 3842 * != 0 != 0 X X ino_c != ino_s 3843 * 3844 * inode number(s) unknown, file names available -> compare file names 3845 * == 0 X OK OK fname_c != fname_s 3846 * X == 0 OK OK fname_c != fname_s 3847 * 3848 * current file doesn't exist, file for swap file exist, file name(s) not 3849 * available -> probably different 3850 * == 0 != 0 FAIL X TRUE 3851 * == 0 != 0 X FAIL TRUE 3852 * 3853 * current file exists, inode for swap unknown, file name(s) not 3854 * available -> probably different 3855 * != 0 == 0 FAIL X TRUE 3856 * != 0 == 0 X FAIL TRUE 3857 * 3858 * current file doesn't exist, inode for swap unknown, one file name not 3859 * available -> probably different 3860 * == 0 == 0 FAIL OK TRUE 3861 * == 0 == 0 OK FAIL TRUE 3862 * 3863 * current file doesn't exist, inode for swap unknown, both file names not 3864 * available -> probably same file 3865 * == 0 == 0 FAIL FAIL FALSE 3866 * 3867 * Note that when the ino_t is 64 bits, only the last 32 will be used. This 3868 * can't be changed without making the block 0 incompatible with 32 bit 3869 * versions. 3870 */ 3871 3872 static int 3873 fnamecmp_ino(fname_c, fname_s, ino_block0) 3874 char_u *fname_c; /* current file name */ 3875 char_u *fname_s; /* file name from swap file */ 3876 long ino_block0; 3877 { 3878 struct stat st; 3879 ino_t ino_c = 0; /* ino of current file */ 3880 ino_t ino_s; /* ino of file from swap file */ 3881 char_u buf_c[MAXPATHL]; /* full path of fname_c */ 3882 char_u buf_s[MAXPATHL]; /* full path of fname_s */ 3883 int retval_c; /* flag: buf_c valid */ 3884 int retval_s; /* flag: buf_s valid */ 3885 3886 if (mch_stat((char *)fname_c, &st) == 0) 3887 ino_c = (ino_t)st.st_ino; 3888 3889 /* 3890 * First we try to get the inode from the file name, because the inode in 3891 * the swap file may be outdated. If that fails (e.g. this path is not 3892 * valid on this machine), use the inode from block 0. 3893 */ 3894 if (mch_stat((char *)fname_s, &st) == 0) 3895 ino_s = (ino_t)st.st_ino; 3896 else 3897 ino_s = (ino_t)ino_block0; 3898 3899 if (ino_c && ino_s) 3900 return (ino_c != ino_s); 3901 3902 /* 3903 * One of the inode numbers is unknown, try a forced vim_FullName() and 3904 * compare the file names. 3905 */ 3906 retval_c = vim_FullName(fname_c, buf_c, MAXPATHL, TRUE); 3907 retval_s = vim_FullName(fname_s, buf_s, MAXPATHL, TRUE); 3908 if (retval_c == OK && retval_s == OK) 3909 return (STRCMP(buf_c, buf_s) != 0); 3910 3911 /* 3912 * Can't compare inodes or file names, guess that the files are different, 3913 * unless both appear not to exist at all. 3914 */ 3915 if (ino_s == 0 && ino_c == 0 && retval_c == FAIL && retval_s == FAIL) 3916 return FALSE; 3917 return TRUE; 3918 } 3919 #endif /* CHECK_INODE */ 3920 3921 /* 3922 * Move a long integer into a four byte character array. 3923 * Used for machine independency in block zero. 3924 */ 3925 static void 3926 long_to_char(n, s) 3927 long n; 3928 char_u *s; 3929 { 3930 s[0] = (char_u)(n & 0xff); 3931 n = (unsigned)n >> 8; 3932 s[1] = (char_u)(n & 0xff); 3933 n = (unsigned)n >> 8; 3934 s[2] = (char_u)(n & 0xff); 3935 n = (unsigned)n >> 8; 3936 s[3] = (char_u)(n & 0xff); 3937 } 3938 3939 static long 3940 char_to_long(s) 3941 char_u *s; 3942 { 3943 long retval; 3944 3945 retval = s[3]; 3946 retval <<= 8; 3947 retval |= s[2]; 3948 retval <<= 8; 3949 retval |= s[1]; 3950 retval <<= 8; 3951 retval |= s[0]; 3952 3953 return retval; 3954 } 3955 3956 void 3957 ml_setdirty(buf, flag) 3958 buf_T *buf; 3959 int flag; 3960 { 3961 bhdr_T *hp; 3962 ZERO_BL *b0p; 3963 3964 if (!buf->b_ml.ml_mfp) 3965 return; 3966 for (hp = buf->b_ml.ml_mfp->mf_used_last; hp != NULL; hp = hp->bh_prev) 3967 { 3968 if (hp->bh_bnum == 0) 3969 { 3970 b0p = (ZERO_BL *)(hp->bh_data); 3971 b0p->b0_dirty = flag ? 0x55 : 0; 3972 hp->bh_flags |= BH_DIRTY; 3973 mf_sync(buf->b_ml.ml_mfp, MFS_ZERO); 3974 break; 3975 } 3976 } 3977 } 3978 3979 #if defined(FEAT_BYTEOFF) || defined(PROTO) 3980 3981 #define MLCS_MAXL 800 /* max no of lines in chunk */ 3982 #define MLCS_MINL 400 /* should be half of MLCS_MAXL */ 3983 3984 /* 3985 * Keep information for finding byte offset of a line, updtytpe may be one of: 3986 * ML_CHNK_ADDLINE: Add len to parent chunk, possibly splitting it 3987 * Careful: ML_CHNK_ADDLINE may cause ml_find_line() to be called. 3988 * ML_CHNK_DELLINE: Subtract len from parent chunk, possibly deleting it 3989 * ML_CHNK_UPDLINE: Add len to parent chunk, as a signed entity. 3990 */ 3991 static void 3992 ml_updatechunk(buf, line, len, updtype) 3993 buf_T *buf; 3994 linenr_T line; 3995 long len; 3996 int updtype; 3997 { 3998 static buf_T *ml_upd_lastbuf = NULL; 3999 static linenr_T ml_upd_lastline; 4000 static linenr_T ml_upd_lastcurline; 4001 static int ml_upd_lastcurix; 4002 4003 linenr_T curline = ml_upd_lastcurline; 4004 int curix = ml_upd_lastcurix; 4005 long size; 4006 chunksize_T *curchnk; 4007 int rest; 4008 bhdr_T *hp; 4009 DATA_BL *dp; 4010 4011 if (buf->b_ml.ml_usedchunks == -1 || len == 0) 4012 return; 4013 if (buf->b_ml.ml_chunksize == NULL) 4014 { 4015 buf->b_ml.ml_chunksize = (chunksize_T *) 4016 alloc((unsigned)sizeof(chunksize_T) * 100); 4017 if (buf->b_ml.ml_chunksize == NULL) 4018 { 4019 buf->b_ml.ml_usedchunks = -1; 4020 return; 4021 } 4022 buf->b_ml.ml_numchunks = 100; 4023 buf->b_ml.ml_usedchunks = 1; 4024 buf->b_ml.ml_chunksize[0].mlcs_numlines = 1; 4025 buf->b_ml.ml_chunksize[0].mlcs_totalsize = 1; 4026 } 4027 4028 if (updtype == ML_CHNK_UPDLINE && buf->b_ml.ml_line_count == 1) 4029 { 4030 /* 4031 * First line in empty buffer from ml_flush_line() -- reset 4032 */ 4033 buf->b_ml.ml_usedchunks = 1; 4034 buf->b_ml.ml_chunksize[0].mlcs_numlines = 1; 4035 buf->b_ml.ml_chunksize[0].mlcs_totalsize = 4036 (long)STRLEN(buf->b_ml.ml_line_ptr) + 1; 4037 return; 4038 } 4039 4040 /* 4041 * Find chunk that our line belongs to, curline will be at start of the 4042 * chunk. 4043 */ 4044 if (buf != ml_upd_lastbuf || line != ml_upd_lastline + 1 4045 || updtype != ML_CHNK_ADDLINE) 4046 { 4047 for (curline = 1, curix = 0; 4048 curix < buf->b_ml.ml_usedchunks - 1 4049 && line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines; 4050 curix++) 4051 { 4052 curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines; 4053 } 4054 } 4055 else if (line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines 4056 && curix < buf->b_ml.ml_usedchunks - 1) 4057 { 4058 /* Adjust cached curix & curline */ 4059 curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines; 4060 curix++; 4061 } 4062 curchnk = buf->b_ml.ml_chunksize + curix; 4063 4064 if (updtype == ML_CHNK_DELLINE) 4065 len *= -1; 4066 curchnk->mlcs_totalsize += len; 4067 if (updtype == ML_CHNK_ADDLINE) 4068 { 4069 curchnk->mlcs_numlines++; 4070 4071 /* May resize here so we don't have to do it in both cases below */ 4072 if (buf->b_ml.ml_usedchunks + 1 >= buf->b_ml.ml_numchunks) 4073 { 4074 buf->b_ml.ml_numchunks = buf->b_ml.ml_numchunks * 3 / 2; 4075 buf->b_ml.ml_chunksize = (chunksize_T *) 4076 vim_realloc(buf->b_ml.ml_chunksize, 4077 sizeof(chunksize_T) * buf->b_ml.ml_numchunks); 4078 if (buf->b_ml.ml_chunksize == NULL) 4079 { 4080 /* Hmmmm, Give up on offset for this buffer */ 4081 buf->b_ml.ml_usedchunks = -1; 4082 return; 4083 } 4084 } 4085 4086 if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MAXL) 4087 { 4088 int count; /* number of entries in block */ 4089 int idx; 4090 int text_end; 4091 int linecnt; 4092 4093 mch_memmove(buf->b_ml.ml_chunksize + curix + 1, 4094 buf->b_ml.ml_chunksize + curix, 4095 (buf->b_ml.ml_usedchunks - curix) * 4096 sizeof(chunksize_T)); 4097 /* Compute length of first half of lines in the splitted chunk */ 4098 size = 0; 4099 linecnt = 0; 4100 while (curline < buf->b_ml.ml_line_count 4101 && linecnt < MLCS_MINL) 4102 { 4103 if ((hp = ml_find_line(buf, curline, ML_FIND)) == NULL) 4104 { 4105 buf->b_ml.ml_usedchunks = -1; 4106 return; 4107 } 4108 dp = (DATA_BL *)(hp->bh_data); 4109 count = (long)(buf->b_ml.ml_locked_high) - 4110 (long)(buf->b_ml.ml_locked_low) + 1; 4111 idx = curline - buf->b_ml.ml_locked_low; 4112 curline = buf->b_ml.ml_locked_high + 1; 4113 if (idx == 0)/* first line in block, text at the end */ 4114 text_end = dp->db_txt_end; 4115 else 4116 text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK); 4117 /* Compute index of last line to use in this MEMLINE */ 4118 rest = count - idx; 4119 if (linecnt + rest > MLCS_MINL) 4120 { 4121 idx += MLCS_MINL - linecnt - 1; 4122 linecnt = MLCS_MINL; 4123 } 4124 else 4125 { 4126 idx = count - 1; 4127 linecnt += rest; 4128 } 4129 size += text_end - ((dp->db_index[idx]) & DB_INDEX_MASK); 4130 } 4131 buf->b_ml.ml_chunksize[curix].mlcs_numlines = linecnt; 4132 buf->b_ml.ml_chunksize[curix + 1].mlcs_numlines -= linecnt; 4133 buf->b_ml.ml_chunksize[curix].mlcs_totalsize = size; 4134 buf->b_ml.ml_chunksize[curix + 1].mlcs_totalsize -= size; 4135 buf->b_ml.ml_usedchunks++; 4136 ml_upd_lastbuf = NULL; /* Force recalc of curix & curline */ 4137 return; 4138 } 4139 else if (buf->b_ml.ml_chunksize[curix].mlcs_numlines >= MLCS_MINL 4140 && curix == buf->b_ml.ml_usedchunks - 1 4141 && buf->b_ml.ml_line_count - line <= 1) 4142 { 4143 /* 4144 * We are in the last chunk and it is cheap to crate a new one 4145 * after this. Do it now to avoid the loop above later on 4146 */ 4147 curchnk = buf->b_ml.ml_chunksize + curix + 1; 4148 buf->b_ml.ml_usedchunks++; 4149 if (line == buf->b_ml.ml_line_count) 4150 { 4151 curchnk->mlcs_numlines = 0; 4152 curchnk->mlcs_totalsize = 0; 4153 } 4154 else 4155 { 4156 /* 4157 * Line is just prior to last, move count for last 4158 * This is the common case when loading a new file 4159 */ 4160 hp = ml_find_line(buf, buf->b_ml.ml_line_count, ML_FIND); 4161 if (hp == NULL) 4162 { 4163 buf->b_ml.ml_usedchunks = -1; 4164 return; 4165 } 4166 dp = (DATA_BL *)(hp->bh_data); 4167 if (dp->db_line_count == 1) 4168 rest = dp->db_txt_end - dp->db_txt_start; 4169 else 4170 rest = 4171 ((dp->db_index[dp->db_line_count - 2]) & DB_INDEX_MASK) 4172 - dp->db_txt_start; 4173 curchnk->mlcs_totalsize = rest; 4174 curchnk->mlcs_numlines = 1; 4175 curchnk[-1].mlcs_totalsize -= rest; 4176 curchnk[-1].mlcs_numlines -= 1; 4177 } 4178 } 4179 } 4180 else if (updtype == ML_CHNK_DELLINE) 4181 { 4182 curchnk->mlcs_numlines--; 4183 ml_upd_lastbuf = NULL; /* Force recalc of curix & curline */ 4184 if (curix < (buf->b_ml.ml_usedchunks - 1) 4185 && (curchnk->mlcs_numlines + curchnk[1].mlcs_numlines) 4186 <= MLCS_MINL) 4187 { 4188 curix++; 4189 curchnk = buf->b_ml.ml_chunksize + curix; 4190 } 4191 else if (curix == 0 && curchnk->mlcs_numlines <= 0) 4192 { 4193 buf->b_ml.ml_usedchunks--; 4194 mch_memmove(buf->b_ml.ml_chunksize, buf->b_ml.ml_chunksize + 1, 4195 buf->b_ml.ml_usedchunks * sizeof(chunksize_T)); 4196 return; 4197 } 4198 else if (curix == 0 || (curchnk->mlcs_numlines > 10 4199 && (curchnk->mlcs_numlines + curchnk[-1].mlcs_numlines) 4200 > MLCS_MINL)) 4201 { 4202 return; 4203 } 4204 4205 /* Collapse chunks */ 4206 curchnk[-1].mlcs_numlines += curchnk->mlcs_numlines; 4207 curchnk[-1].mlcs_totalsize += curchnk->mlcs_totalsize; 4208 buf->b_ml.ml_usedchunks--; 4209 if (curix < buf->b_ml.ml_usedchunks) 4210 { 4211 mch_memmove(buf->b_ml.ml_chunksize + curix, 4212 buf->b_ml.ml_chunksize + curix + 1, 4213 (buf->b_ml.ml_usedchunks - curix) * 4214 sizeof(chunksize_T)); 4215 } 4216 return; 4217 } 4218 ml_upd_lastbuf = buf; 4219 ml_upd_lastline = line; 4220 ml_upd_lastcurline = curline; 4221 ml_upd_lastcurix = curix; 4222 } 4223 4224 /* 4225 * Find offset for line or line with offset. 4226 * Find line with offset if line is 0; return remaining offset in offp 4227 * Find offset of line if line > 0 4228 * return -1 if information is not available 4229 */ 4230 long 4231 ml_find_line_or_offset(buf, line, offp) 4232 buf_T *buf; 4233 linenr_T line; 4234 long *offp; 4235 { 4236 linenr_T curline; 4237 int curix; 4238 long size; 4239 bhdr_T *hp; 4240 DATA_BL *dp; 4241 int count; /* number of entries in block */ 4242 int idx; 4243 int start_idx; 4244 int text_end; 4245 long offset; 4246 int len; 4247 int ffdos = (get_fileformat(buf) == EOL_DOS); 4248 int extra = 0; 4249 4250 if (buf->b_ml.ml_usedchunks == -1 4251 || buf->b_ml.ml_chunksize == NULL 4252 || line < 0) 4253 return -1; 4254 4255 if (offp == NULL) 4256 offset = 0; 4257 else 4258 offset = *offp; 4259 if (line == 0 && offset <= 0) 4260 return 1; /* Not a "find offset" and offset 0 _must_ be in line 1 */ 4261 /* 4262 * Find the last chunk before the one containing our line. Last chunk is 4263 * special because it will never qualify 4264 */ 4265 curline = 1; 4266 curix = size = 0; 4267 while (curix < buf->b_ml.ml_usedchunks - 1 4268 && ((line != 0 4269 && line >= curline + buf->b_ml.ml_chunksize[curix].mlcs_numlines) 4270 || (offset != 0 4271 && offset > size + buf->b_ml.ml_chunksize[curix].mlcs_totalsize 4272 + ffdos * buf->b_ml.ml_chunksize[curix].mlcs_numlines))) 4273 { 4274 curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines; 4275 size += buf->b_ml.ml_chunksize[curix].mlcs_totalsize; 4276 if (offset && ffdos) 4277 size += buf->b_ml.ml_chunksize[curix].mlcs_numlines; 4278 curix++; 4279 } 4280 4281 while ((line != 0 && curline < line) || (offset != 0 && size < offset)) 4282 { 4283 if (curline > buf->b_ml.ml_line_count 4284 || (hp = ml_find_line(buf, curline, ML_FIND)) == NULL) 4285 return -1; 4286 dp = (DATA_BL *)(hp->bh_data); 4287 count = (long)(buf->b_ml.ml_locked_high) - 4288 (long)(buf->b_ml.ml_locked_low) + 1; 4289 start_idx = idx = curline - buf->b_ml.ml_locked_low; 4290 if (idx == 0)/* first line in block, text at the end */ 4291 text_end = dp->db_txt_end; 4292 else 4293 text_end = ((dp->db_index[idx - 1]) & DB_INDEX_MASK); 4294 /* Compute index of last line to use in this MEMLINE */ 4295 if (line != 0) 4296 { 4297 if (curline + (count - idx) >= line) 4298 idx += line - curline - 1; 4299 else 4300 idx = count - 1; 4301 } 4302 else 4303 { 4304 extra = 0; 4305 while (offset >= size 4306 + text_end - (int)((dp->db_index[idx]) & DB_INDEX_MASK) 4307 + ffdos) 4308 { 4309 if (ffdos) 4310 size++; 4311 if (idx == count - 1) 4312 { 4313 extra = 1; 4314 break; 4315 } 4316 idx++; 4317 } 4318 } 4319 len = text_end - ((dp->db_index[idx]) & DB_INDEX_MASK); 4320 size += len; 4321 if (offset != 0 && size >= offset) 4322 { 4323 if (size + ffdos == offset) 4324 *offp = 0; 4325 else if (idx == start_idx) 4326 *offp = offset - size + len; 4327 else 4328 *offp = offset - size + len 4329 - (text_end - ((dp->db_index[idx - 1]) & DB_INDEX_MASK)); 4330 curline += idx - start_idx + extra; 4331 if (curline > buf->b_ml.ml_line_count) 4332 return -1; /* exactly one byte beyond the end */ 4333 return curline; 4334 } 4335 curline = buf->b_ml.ml_locked_high + 1; 4336 } 4337 4338 if (ffdos) 4339 size += line - 1; 4340 return size; 4341 } 4342 4343 /* 4344 * Goto byte in buffer with offset 'cnt'. 4345 */ 4346 void 4347 goto_byte(cnt) 4348 long cnt; 4349 { 4350 long boff = cnt; 4351 linenr_T lnum; 4352 4353 ml_flush_line(curbuf); /* cached line may be dirty */ 4354 setpcmark(); 4355 if (boff) 4356 --boff; 4357 lnum = ml_find_line_or_offset(curbuf, (linenr_T)0, &boff); 4358 if (lnum < 1) /* past the end */ 4359 { 4360 curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; 4361 curwin->w_curswant = MAXCOL; 4362 coladvance((colnr_T)MAXCOL); 4363 } 4364 else 4365 { 4366 curwin->w_cursor.lnum = lnum; 4367 curwin->w_cursor.col = (colnr_T)boff; 4368 curwin->w_set_curswant = TRUE; 4369 } 4370 check_cursor(); 4371 4372 # ifdef FEAT_MBYTE 4373 /* Make sure the cursor is on the first byte of a multi-byte char. */ 4374 if (has_mbyte) 4375 mb_adjust_cursor(); 4376 # endif 4377 } 4378 #endif 4379